123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- package cwhub
- // Enable/disable items already installed (no downloading here)
- // This file is not named install.go to avoid confusion with the functions in helpers.go
- import (
- "fmt"
- "os"
- "path/filepath"
- log "github.com/sirupsen/logrus"
- )
- // creates symlink between actual config file at hub.HubDir and hub.ConfigDir
- // Handles collections recursively
- func (h *Hub) EnableItem(target *Item) error {
- var err error
- parentDir := filepath.Clean(h.cfg.InstallDir + "/" + target.Type + "/" + target.Stage + "/")
- // create directories if needed
- if target.Installed {
- if target.Tainted {
- return fmt.Errorf("%s is tainted, won't enable unless --force", target.Name)
- }
- if target.Local {
- return fmt.Errorf("%s is local, won't enable", target.Name)
- }
- // if it's a collection, check sub-items even if the collection file itself is up-to-date
- if target.UpToDate && target.Type != COLLECTIONS {
- log.Tracef("%s is installed and up-to-date, skip.", target.Name)
- return nil
- }
- }
- if _, err = os.Stat(parentDir); os.IsNotExist(err) {
- log.Infof("%s doesn't exist, create", parentDir)
- if err = os.MkdirAll(parentDir, os.ModePerm); err != nil {
- return fmt.Errorf("while creating directory: %w", err)
- }
- }
- // install sub-items if it's a collection
- if target.Type == COLLECTIONS {
- for _, sub := range target.SubItems() {
- val, ok := h.Items[sub.Type][sub.Name]
- if !ok {
- return fmt.Errorf("required %s %s of %s doesn't exist, abort", sub.Type, sub.Name, target.Name)
- }
- err = h.EnableItem(&val)
- if err != nil {
- return fmt.Errorf("while installing %s: %w", sub.Name, err)
- }
- }
- }
- // check if file already exists where it should in configdir (eg /etc/crowdsec/collections/)
- if _, err = os.Lstat(parentDir + "/" + target.FileName); !os.IsNotExist(err) {
- log.Infof("%s already exists.", parentDir+"/"+target.FileName)
- return nil
- }
- // hub.ConfigDir + target.RemotePath
- srcPath, err := filepath.Abs(h.cfg.HubDir + "/" + target.RemotePath)
- if err != nil {
- return fmt.Errorf("while getting source path: %w", err)
- }
- dstPath, err := filepath.Abs(parentDir + "/" + target.FileName)
- if err != nil {
- return fmt.Errorf("while getting destination path: %w", err)
- }
- if err = os.Symlink(srcPath, dstPath); err != nil {
- return fmt.Errorf("while creating symlink from %s to %s: %w", srcPath, dstPath, err)
- }
- log.Infof("Enabled %s : %s", target.Type, target.Name)
- target.Installed = true
- h.Items[target.Type][target.Name] = *target
- return nil
- }
- func (h *Hub) purgeItem(target Item) (Item, error) {
- itempath := h.cfg.HubDir + "/" + target.RemotePath
- // disable hub file
- if err := os.Remove(itempath); err != nil {
- return target, fmt.Errorf("while removing file: %w", err)
- }
- target.Downloaded = false
- log.Infof("Removed source file [%s]: %s", target.Name, itempath)
- h.Items[target.Type][target.Name] = target
- return target, nil
- }
- // DisableItem to disable an item managed by the hub, removes the symlink if purge is true
- func (h *Hub) DisableItem(target *Item, purge bool, force bool) error {
- var err error
- // already disabled, noop unless purge
- if !target.Installed {
- if purge {
- *target, err = h.purgeItem(*target)
- if err != nil {
- return err
- }
- }
- return nil
- }
- if target.Local {
- return fmt.Errorf("%s isn't managed by hub. Please delete manually", target.Name)
- }
- if target.Tainted && !force {
- return fmt.Errorf("%s is tainted, use '--force' to overwrite", target.Name)
- }
- // for a COLLECTIONS, disable sub-items
- if target.Type == COLLECTIONS {
- for _, sub := range target.SubItems() {
- val, ok := h.Items[sub.Type][sub.Name]
- if !ok {
- log.Errorf("Referred %s %s in collection %s doesn't exist.", sub.Type, sub.Name, target.Name)
- continue
- }
- // check if the item doesn't belong to another collection before removing it
- toRemove := true
- for _, collection := range val.BelongsToCollections {
- if collection != target.Name {
- toRemove = false
- break
- }
- }
- if toRemove {
- err = h.DisableItem(&val, purge, force)
- if err != nil {
- return fmt.Errorf("while disabling %s: %w", sub.Name, err)
- }
- } else {
- log.Infof("%s was not removed because it belongs to another collection", val.Name)
- }
- }
- }
- syml, err := filepath.Abs(h.cfg.InstallDir + "/" + target.Type + "/" + target.Stage + "/" + target.FileName)
- if err != nil {
- return err
- }
- stat, err := os.Lstat(syml)
- if os.IsNotExist(err) {
- // we only accept to "delete" non existing items if it's a forced purge
- if !purge && !force {
- return fmt.Errorf("can't delete %s : %s doesn't exist", target.Name, syml)
- }
- } else {
- // if it's managed by hub, it's a symlink to csconfig.GConfig.hub.HubDir / ...
- if stat.Mode()&os.ModeSymlink == 0 {
- log.Warningf("%s (%s) isn't a symlink, can't disable", target.Name, syml)
- return fmt.Errorf("%s isn't managed by hub", target.Name)
- }
- hubpath, err := os.Readlink(syml)
- if err != nil {
- return fmt.Errorf("while reading symlink: %w", err)
- }
- absPath, err := filepath.Abs(h.cfg.HubDir + "/" + target.RemotePath)
- if err != nil {
- return fmt.Errorf("while abs path: %w", err)
- }
- if hubpath != absPath {
- log.Warningf("%s (%s) isn't a symlink to %s", target.Name, syml, absPath)
- return fmt.Errorf("%s isn't managed by hub", target.Name)
- }
- // remove the symlink
- if err = os.Remove(syml); err != nil {
- return fmt.Errorf("while removing symlink: %w", err)
- }
- log.Infof("Removed symlink [%s] : %s", target.Name, syml)
- }
- target.Installed = false
- if purge {
- *target, err = h.purgeItem(*target)
- if err != nil {
- return err
- }
- }
- h.Items[target.Type][target.Name] = *target
- return nil
- }
|