Refact pkg/cwhub (part 3) (#2516)
* removed unused error; comment * rename loop variables * happy path * rename loop variables * extract function, method * log.Printf -> log.Infof * tests -> testdata from "go help test": The go tool will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests. * align tags * extract function toEmoji
This commit is contained in:
parent
3253b16f0f
commit
89028f17cf
10 changed files with 205 additions and 173 deletions
|
@ -47,24 +47,24 @@ type ItemHubStatus struct {
|
|||
// Item can be: parsed, scenario, collection
|
||||
type Item struct {
|
||||
// descriptive info
|
||||
Type string `yaml:"type,omitempty" json:"type,omitempty"` // parser|postoverflows|scenario|collection(|enrich)
|
||||
Stage string `json:"stage,omitempty" yaml:"stage,omitempty,omitempty"` // Stage for parser|postoverflow: s00-raw/s01-...
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"` // parser|postoverflows|scenario|collection(|enrich)
|
||||
Stage string `json:"stage,omitempty" yaml:"stage,omitempty"` // Stage for parser|postoverflow: s00-raw/s01-...
|
||||
Name string `json:"name,omitempty"` // as seen in .config.json, usually "author/name"
|
||||
FileName string `json:"file_name,omitempty"` // the filename, ie. apache2-logs.yaml
|
||||
Description string `yaml:"description,omitempty" json:"description,omitempty"` // as seen in .config.json
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"` // as seen in .config.json
|
||||
Author string `json:"author,omitempty"` // as seen in .config.json
|
||||
References []string `yaml:"references,omitempty" json:"references,omitempty"` // as seen in .config.json
|
||||
BelongsToCollections []string `yaml:"belongs_to_collections,omitempty" json:"belongs_to_collections,omitempty"` // if it's part of collections, track name here
|
||||
References []string `json:"references,omitempty" yaml:"references,omitempty"` // as seen in .config.json
|
||||
BelongsToCollections []string `json:"belongs_to_collections,omitempty" yaml:"belongs_to_collections,omitempty"` // if it's part of collections, track name here
|
||||
|
||||
// remote (hub) infos
|
||||
RemoteURL string `yaml:"remoteURL,omitempty" json:"remoteURL,omitempty"` // the full remote uri of file in http
|
||||
RemotePath string `json:"path,omitempty" yaml:"remote_path,omitempty"` // the path relative to git ie. /parsers/stage/author/file.yaml
|
||||
RemoteHash string `yaml:"hash,omitempty" json:"hash,omitempty"` // the meow
|
||||
Version string `json:"version,omitempty"` // the last version
|
||||
Versions map[string]ItemVersion `json:"versions,omitempty" yaml:"-"` // the list of existing versions
|
||||
// remote (hub) info
|
||||
RemoteURL string `json:"remoteURL,omitempty" yaml:"remoteURL,omitempty"` // the full remote uri of file in http
|
||||
RemotePath string `json:"path,omitempty" yaml:"remote_path,omitempty"` // the path relative to git ie. /parsers/stage/author/file.yaml
|
||||
RemoteHash string `json:"hash,omitempty" yaml:"hash,omitempty"` // the meow
|
||||
Version string `json:"version,omitempty"` // the last version
|
||||
Versions map[string]ItemVersion `json:"versions,omitempty" yaml:"-"` // the list of existing versions
|
||||
|
||||
// local (deployed) infos
|
||||
LocalPath string `yaml:"local_path,omitempty" json:"local_path,omitempty"` // the local path relative to ${CFG_DIR}
|
||||
// local (deployed) info
|
||||
LocalPath string `json:"local_path,omitempty" yaml:"local_path,omitempty"` // the local path relative to ${CFG_DIR}
|
||||
// LocalHubPath string
|
||||
LocalVersion string `json:"local_version,omitempty"`
|
||||
LocalHash string `json:"local_hash,omitempty"` // the local meow
|
||||
|
@ -75,41 +75,52 @@ type Item struct {
|
|||
Local bool `json:"local,omitempty"` // if it's a non versioned control one
|
||||
|
||||
// if it's a collection, it not a single file
|
||||
Parsers []string `yaml:"parsers,omitempty" json:"parsers,omitempty"`
|
||||
PostOverflows []string `yaml:"postoverflows,omitempty" json:"postoverflows,omitempty"`
|
||||
Scenarios []string `yaml:"scenarios,omitempty" json:"scenarios,omitempty"`
|
||||
Collections []string `yaml:"collections,omitempty" json:"collections,omitempty"`
|
||||
Parsers []string `json:"parsers,omitempty" yaml:"parsers,omitempty"`
|
||||
PostOverflows []string `json:"postoverflows,omitempty" yaml:"postoverflows,omitempty"`
|
||||
Scenarios []string `json:"scenarios,omitempty" yaml:"scenarios,omitempty"`
|
||||
Collections []string `json:"collections,omitempty" yaml:"collections,omitempty"`
|
||||
}
|
||||
|
||||
func toEmoji(managed bool, installed bool, warning bool, ok bool) emoji.Emoji {
|
||||
if !managed {
|
||||
return emoji.House
|
||||
}
|
||||
|
||||
if !installed {
|
||||
return emoji.Prohibited
|
||||
}
|
||||
|
||||
if warning {
|
||||
return emoji.Warning
|
||||
}
|
||||
|
||||
if ok {
|
||||
return emoji.CheckMark
|
||||
}
|
||||
|
||||
// XXX: this is new
|
||||
return emoji.QuestionMark
|
||||
}
|
||||
|
||||
func (i *Item) toHubStatus() ItemHubStatus {
|
||||
hubStatus := ItemHubStatus{}
|
||||
hubStatus.Name = i.Name
|
||||
hubStatus.LocalVersion = i.LocalVersion
|
||||
hubStatus.LocalPath = i.LocalPath
|
||||
hubStatus.Description = i.Description
|
||||
|
||||
status, ok, warning, managed := ItemStatus(*i)
|
||||
hubStatus.Status = status
|
||||
|
||||
if !managed {
|
||||
hubStatus.UTF8_Status = fmt.Sprintf("%v %s", emoji.House, status)
|
||||
} else if !i.Installed {
|
||||
hubStatus.UTF8_Status = fmt.Sprintf("%v %s", emoji.Prohibited, status)
|
||||
} else if warning {
|
||||
hubStatus.UTF8_Status = fmt.Sprintf("%v %s", emoji.Warning, status)
|
||||
} else if ok {
|
||||
hubStatus.UTF8_Status = fmt.Sprintf("%v %s", emoji.CheckMark, status)
|
||||
return ItemHubStatus{
|
||||
Name: i.Name,
|
||||
LocalVersion: i.LocalVersion,
|
||||
LocalPath: i.LocalPath,
|
||||
Description: i.Description,
|
||||
Status: status,
|
||||
UTF8_Status: fmt.Sprintf("%v %s", toEmoji(managed, i.Installed, warning, ok), status),
|
||||
}
|
||||
|
||||
return hubStatus
|
||||
}
|
||||
|
||||
// XXX: can we remove these globals?
|
||||
var skippedLocal = 0
|
||||
var skippedTainted = 0
|
||||
|
||||
// To be used when reference(s) (is/are) missing in a collection
|
||||
var ReferenceMissingError = errors.New("Reference(s) missing in collection")
|
||||
var MissingHubIndex = errors.New("hub index can't be found")
|
||||
|
||||
// GetVersionStatus: semver requires 'v' prefix
|
||||
func GetVersionStatus(v *Item) int {
|
||||
|
@ -203,11 +214,11 @@ func AddItem(itemType string, item Item) error {
|
|||
}
|
||||
|
||||
func DisplaySummary() {
|
||||
log.Printf("Loaded %d collecs, %d parsers, %d scenarios, %d post-overflow parsers", len(hubIdx[COLLECTIONS]),
|
||||
log.Infof("Loaded %d collecs, %d parsers, %d scenarios, %d post-overflow parsers", len(hubIdx[COLLECTIONS]),
|
||||
len(hubIdx[PARSERS]), len(hubIdx[SCENARIOS]), len(hubIdx[PARSERS_OVFLW]))
|
||||
|
||||
if skippedLocal > 0 || skippedTainted > 0 {
|
||||
log.Printf("unmanaged items: %d local, %d tainted", skippedLocal, skippedTainted)
|
||||
log.Infof("unmanaged items: %d local, %d tainted", skippedLocal, skippedTainted)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ func TestInstallCollection(t *testing.T) {
|
|||
|
||||
it = hubIdx[COLLECTIONS][it.Name]
|
||||
x := GetHubStatusForItemType(COLLECTIONS, it.Name, false)
|
||||
log.Printf("%+v", x)
|
||||
log.Infof("%+v", x)
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -425,7 +425,7 @@ func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
}
|
||||
response.Header.Set("Content-Type", "application/json")
|
||||
|
||||
log.Printf("---> %s", req.URL.Path)
|
||||
log.Infof("---> %s", req.URL.Path)
|
||||
|
||||
// FAKE PARSER
|
||||
resp, ok := responseByPath[req.URL.Path]
|
||||
|
@ -455,10 +455,10 @@ func fileToStringX(path string) string {
|
|||
|
||||
func resetResponseByPath() {
|
||||
responseByPath = map[string]string{
|
||||
"/master/parsers/s01-parse/crowdsecurity/foobar_parser.yaml": fileToStringX("./tests/foobar_parser.yaml"),
|
||||
"/master/parsers/s01-parse/crowdsecurity/foobar_subparser.yaml": fileToStringX("./tests/foobar_parser.yaml"),
|
||||
"/master/collections/crowdsecurity/test_collection.yaml": fileToStringX("./tests/collection_v1.yaml"),
|
||||
"/master/.index.json": fileToStringX("./tests/index1.json"),
|
||||
"/master/parsers/s01-parse/crowdsecurity/foobar_parser.yaml": fileToStringX("./testdata/foobar_parser.yaml"),
|
||||
"/master/parsers/s01-parse/crowdsecurity/foobar_subparser.yaml": fileToStringX("./testdata/foobar_parser.yaml"),
|
||||
"/master/collections/crowdsecurity/test_collection.yaml": fileToStringX("./testdata/collection_v1.yaml"),
|
||||
"/master/.index.json": fileToStringX("./testdata/index1.json"),
|
||||
"/master/scenarios/crowdsecurity/foobar_scenario.yaml": `filter: true
|
||||
name: crowdsecurity/foobar_scenario`,
|
||||
"/master/scenarios/crowdsecurity/barfoo_scenario.yaml": `filter: true
|
||||
|
|
|
@ -158,6 +158,6 @@ func assertCollectionDepsInstalled(t *testing.T, collection string) {
|
|||
}
|
||||
|
||||
func pushUpdateToCollectionInHub() {
|
||||
responseByPath["/master/.index.json"] = fileToStringX("./tests/index2.json")
|
||||
responseByPath["/master/collections/crowdsecurity/test_collection.yaml"] = fileToStringX("./tests/collection_v2.yaml")
|
||||
responseByPath["/master/.index.json"] = fileToStringX("./testdata/index2.json")
|
||||
responseByPath["/master/collections/crowdsecurity/test_collection.yaml"] = fileToStringX("./testdata/collection_v2.yaml")
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ func EnableItem(hub *csconfig.Hub, target Item) (Item, error) {
|
|||
}
|
||||
|
||||
if _, err := os.Stat(parent_dir); os.IsNotExist(err) {
|
||||
log.Printf("%s doesn't exist, create", parent_dir)
|
||||
log.Infof("%s doesn't exist, create", parent_dir)
|
||||
|
||||
if err := os.MkdirAll(parent_dir, os.ModePerm); err != nil {
|
||||
return target, fmt.Errorf("while creating directory: %w", err)
|
||||
|
@ -187,7 +187,7 @@ func EnableItem(hub *csconfig.Hub, target Item) (Item, error) {
|
|||
|
||||
// check if file already exists where it should in configdir (eg /etc/crowdsec/collections/)
|
||||
if _, err := os.Lstat(parent_dir + "/" + target.FileName); !os.IsNotExist(err) {
|
||||
log.Printf("%s already exists.", parent_dir+"/"+target.FileName)
|
||||
log.Infof("%s already exists.", parent_dir+"/"+target.FileName)
|
||||
return target, nil
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ func EnableItem(hub *csconfig.Hub, target Item) (Item, error) {
|
|||
return target, fmt.Errorf("while creating symlink from %s to %s: %w", srcPath, dstPath, err)
|
||||
}
|
||||
|
||||
log.Printf("Enabled %s : %s", target.Type, target.Name)
|
||||
log.Infof("Enabled %s : %s", target.Type, target.Name)
|
||||
target.Installed = true
|
||||
hubIdx[target.Type][target.Name] = target
|
||||
|
||||
|
|
|
@ -14,10 +14,35 @@ import (
|
|||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
)
|
||||
|
||||
func isYAMLFileName(path string) bool {
|
||||
return strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml")
|
||||
}
|
||||
|
||||
func validItemFileName(vname string, fauthor string, fname string) bool {
|
||||
return (fauthor+"/"+fname == vname+".yaml") || (fauthor+"/"+fname == vname+".yml")
|
||||
}
|
||||
|
||||
func handleSymlink(path string) (string, error) {
|
||||
hubpath, err := os.Readlink(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to read symlink of %s", path)
|
||||
}
|
||||
// the symlink target doesn't exist, user might have removed ~/.hub/hub/...yaml without deleting /etc/crowdsec/....yaml
|
||||
_, err = os.Lstat(hubpath)
|
||||
if os.IsNotExist(err) {
|
||||
log.Infof("%s is a symlink to %s that doesn't exist, deleting symlink", path, hubpath)
|
||||
// remove the symlink
|
||||
if err = os.Remove(path); err != nil {
|
||||
return "", fmt.Errorf("failed to unlink %s: %w", path, err)
|
||||
}
|
||||
|
||||
// XXX: is this correct?
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return hubpath, nil
|
||||
}
|
||||
|
||||
type walker struct {
|
||||
// the walk/parserVisit function can't receive extra args
|
||||
hubdir string
|
||||
|
@ -80,7 +105,7 @@ func (w walker) getItemInfo(path string) (itemFileInfo, bool, error) {
|
|||
}
|
||||
|
||||
log.Tracef("stage:%s ftype:%s", ret.stage, ret.ftype)
|
||||
// log.Printf("%s -> name:%s stage:%s", path, fname, stage)
|
||||
// log.Infof("%s -> name:%s stage:%s", path, fname, stage)
|
||||
|
||||
if ret.stage == SCENARIOS {
|
||||
ret.ftype = SCENARIOS
|
||||
|
@ -120,8 +145,7 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// we only care about yaml files
|
||||
if !strings.HasSuffix(f.Name(), ".yaml") && !strings.HasSuffix(f.Name(), ".yml") {
|
||||
if !isYAMLFileName(f.Name()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -141,28 +165,23 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
|
||||
log.Tracef("%s isn't a symlink", path)
|
||||
} else {
|
||||
hubpath, err = os.Readlink(path)
|
||||
hubpath, err = handleSymlink(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read symlink of %s", path)
|
||||
}
|
||||
// the symlink target doesn't exist, user might have removed ~/.hub/hub/...yaml without deleting /etc/crowdsec/....yaml
|
||||
_, err := os.Lstat(hubpath)
|
||||
if os.IsNotExist(err) {
|
||||
log.Infof("%s is a symlink to %s that doesn't exist, deleting symlink", path, hubpath)
|
||||
// remove the symlink
|
||||
if err = os.Remove(path); err != nil {
|
||||
return fmt.Errorf("failed to unlink %s: %w", path, err)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
log.Tracef("%s points to %s", path, hubpath)
|
||||
|
||||
if hubpath == "" {
|
||||
// XXX: is this correct?
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// if it's not a symlink and not in hub, it's a local file, don't bother
|
||||
if local && !inhub {
|
||||
log.Tracef("%s is a local file, skip", path)
|
||||
skippedLocal++
|
||||
// log.Printf("local scenario, skip.")
|
||||
// log.Infof("local scenario, skip.")
|
||||
|
||||
_, fileName := filepath.Split(path)
|
||||
|
||||
|
@ -185,36 +204,36 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
|
||||
match := false
|
||||
|
||||
for k, v := range hubIdx[info.ftype] {
|
||||
log.Tracef("check [%s] vs [%s] : %s", info.fname, v.RemotePath, info.ftype+"/"+info.stage+"/"+info.fname+".yaml")
|
||||
for name, item := range hubIdx[info.ftype] {
|
||||
log.Tracef("check [%s] vs [%s] : %s", info.fname, item.RemotePath, info.ftype+"/"+info.stage+"/"+info.fname+".yaml")
|
||||
|
||||
if info.fname != v.FileName {
|
||||
log.Tracef("%s != %s (filename)", info.fname, v.FileName)
|
||||
if info.fname != item.FileName {
|
||||
log.Tracef("%s != %s (filename)", info.fname, item.FileName)
|
||||
continue
|
||||
}
|
||||
|
||||
// wrong stage
|
||||
if v.Stage != info.stage {
|
||||
if item.Stage != info.stage {
|
||||
continue
|
||||
}
|
||||
|
||||
// if we are walking hub dir, just mark present files as downloaded
|
||||
if inhub {
|
||||
// wrong author
|
||||
if info.fauthor != v.Author {
|
||||
if info.fauthor != item.Author {
|
||||
continue
|
||||
}
|
||||
|
||||
// wrong file
|
||||
if !validItemFileName(v.Name, info.fauthor, info.fname) {
|
||||
if !validItemFileName(item.Name, info.fauthor, info.fname) {
|
||||
continue
|
||||
}
|
||||
|
||||
if path == w.hubdir+"/"+v.RemotePath {
|
||||
log.Tracef("marking %s as downloaded", v.Name)
|
||||
v.Downloaded = true
|
||||
if path == w.hubdir+"/"+item.RemotePath {
|
||||
log.Tracef("marking %s as downloaded", item.Name)
|
||||
item.Downloaded = true
|
||||
}
|
||||
} else if !hasPathSuffix(hubpath, v.RemotePath) {
|
||||
} else if !hasPathSuffix(hubpath, item.RemotePath) {
|
||||
// wrong file
|
||||
// <type>/<stage>/<author>/<name>.yaml
|
||||
continue
|
||||
|
@ -226,36 +245,37 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
}
|
||||
|
||||
// let's reverse sort the versions to deal with hash collisions (#154)
|
||||
versions := make([]string, 0, len(v.Versions))
|
||||
for k := range v.Versions {
|
||||
versions := make([]string, 0, len(item.Versions))
|
||||
for k := range item.Versions {
|
||||
versions = append(versions, k)
|
||||
}
|
||||
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
|
||||
|
||||
for _, version := range versions {
|
||||
val := v.Versions[version]
|
||||
val := item.Versions[version]
|
||||
if sha != val.Digest {
|
||||
// log.Printf("matching filenames, wrong hash %s != %s -- %s", sha, val.Digest, spew.Sdump(v))
|
||||
// log.Infof("matching filenames, wrong hash %s != %s -- %s", sha, val.Digest, spew.Sdump(v))
|
||||
continue
|
||||
}
|
||||
|
||||
v.Downloaded = true
|
||||
v.LocalHash = sha
|
||||
|
||||
// we got an exact match, update struct
|
||||
|
||||
item.Downloaded = true
|
||||
item.LocalHash = sha
|
||||
|
||||
if !inhub {
|
||||
log.Tracef("found exact match for %s, version is %s, latest is %s", v.Name, version, v.Version)
|
||||
v.LocalPath = path
|
||||
v.LocalVersion = version
|
||||
v.Tainted = false
|
||||
log.Tracef("found exact match for %s, version is %s, latest is %s", item.Name, version, item.Version)
|
||||
item.LocalPath = path
|
||||
item.LocalVersion = version
|
||||
item.Tainted = false
|
||||
// if we're walking the hub, present file doesn't means installed file
|
||||
v.Installed = true
|
||||
item.Installed = true
|
||||
}
|
||||
|
||||
if version == v.Version {
|
||||
log.Tracef("%s is up-to-date", v.Name)
|
||||
v.UpToDate = true
|
||||
if version == item.Version {
|
||||
log.Tracef("%s is up-to-date", item.Name)
|
||||
item.UpToDate = true
|
||||
}
|
||||
|
||||
match = true
|
||||
|
@ -264,19 +284,19 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
}
|
||||
|
||||
if !match {
|
||||
log.Tracef("got tainted match for %s : %s", v.Name, path)
|
||||
log.Tracef("got tainted match for %s: %s", item.Name, path)
|
||||
|
||||
skippedTainted++
|
||||
// the file and the stage is right, but the hash is wrong, it has been tainted by user
|
||||
if !inhub {
|
||||
v.LocalPath = path
|
||||
v.Installed = true
|
||||
item.LocalPath = path
|
||||
item.Installed = true
|
||||
}
|
||||
|
||||
v.UpToDate = false
|
||||
v.LocalVersion = "?"
|
||||
v.Tainted = true
|
||||
v.LocalHash = sha
|
||||
item.UpToDate = false
|
||||
item.LocalVersion = "?"
|
||||
item.Tainted = true
|
||||
item.LocalHash = sha
|
||||
}
|
||||
|
||||
// update the entry if appropriate
|
||||
|
@ -286,7 +306,7 @@ func (w walker) parserVisit(path string, f os.DirEntry, err error) error {
|
|||
// } else if !inhub {
|
||||
|
||||
// } else if
|
||||
hubIdx[info.ftype][k] = v
|
||||
hubIdx[info.ftype][name] = item
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -302,71 +322,72 @@ func CollecDepsCheck(v *Item) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if v.Type != COLLECTIONS {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if it's a collection, ensure all the items are installed, or tag it as tainted
|
||||
if v.Type == COLLECTIONS {
|
||||
log.Tracef("checking submembers of %s installed:%t", v.Name, v.Installed)
|
||||
log.Tracef("checking submembers of %s installed:%t", v.Name, v.Installed)
|
||||
|
||||
var tmp = [][]string{v.Parsers, v.PostOverflows, v.Scenarios, v.Collections}
|
||||
for idx, ptr := range tmp {
|
||||
ptrtype := ItemTypes[idx]
|
||||
for _, p := range ptr {
|
||||
val, ok := hubIdx[ptrtype][p]
|
||||
if !ok {
|
||||
log.Fatalf("Referred %s %s in collection %s doesn't exist.", ptrtype, p, v.Name)
|
||||
}
|
||||
|
||||
log.Tracef("check %s installed:%t", val.Name, val.Installed)
|
||||
|
||||
if !v.Installed {
|
||||
continue
|
||||
}
|
||||
|
||||
if val.Type == COLLECTIONS {
|
||||
log.Tracef("collec, recurse.")
|
||||
|
||||
if err := CollecDepsCheck(&val); err != nil {
|
||||
if val.Tainted {
|
||||
v.Tainted = true
|
||||
}
|
||||
|
||||
return fmt.Errorf("sub collection %s is broken: %w", val.Name, err)
|
||||
}
|
||||
|
||||
hubIdx[ptrtype][p] = val
|
||||
}
|
||||
|
||||
// propagate the state of sub-items to set
|
||||
if val.Tainted {
|
||||
v.Tainted = true
|
||||
return fmt.Errorf("tainted %s %s, tainted", ptrtype, p)
|
||||
}
|
||||
|
||||
if !val.Installed && v.Installed {
|
||||
v.Tainted = true
|
||||
return fmt.Errorf("missing %s %s, tainted", ptrtype, p)
|
||||
}
|
||||
|
||||
if !val.UpToDate {
|
||||
v.UpToDate = false
|
||||
return fmt.Errorf("outdated %s %s", ptrtype, p)
|
||||
}
|
||||
|
||||
skip := false
|
||||
|
||||
for idx := range val.BelongsToCollections {
|
||||
if val.BelongsToCollections[idx] == v.Name {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
|
||||
if !skip {
|
||||
val.BelongsToCollections = append(val.BelongsToCollections, v.Name)
|
||||
}
|
||||
|
||||
hubIdx[ptrtype][p] = val
|
||||
|
||||
log.Tracef("checking for %s - tainted:%t uptodate:%t", p, v.Tainted, v.UpToDate)
|
||||
for idx, itemSlice := range [][]string{v.Parsers, v.PostOverflows, v.Scenarios, v.Collections} {
|
||||
sliceType := ItemTypes[idx]
|
||||
for _, subName := range itemSlice {
|
||||
subItem, ok := hubIdx[sliceType][subName]
|
||||
if !ok {
|
||||
log.Fatalf("Referred %s %s in collection %s doesn't exist.", sliceType, subName, v.Name)
|
||||
}
|
||||
|
||||
log.Tracef("check %s installed:%t", subItem.Name, subItem.Installed)
|
||||
|
||||
if !v.Installed {
|
||||
continue
|
||||
}
|
||||
|
||||
if subItem.Type == COLLECTIONS {
|
||||
log.Tracef("collec, recurse.")
|
||||
|
||||
if err := CollecDepsCheck(&subItem); err != nil {
|
||||
if subItem.Tainted {
|
||||
v.Tainted = true
|
||||
}
|
||||
|
||||
return fmt.Errorf("sub collection %s is broken: %w", subItem.Name, err)
|
||||
}
|
||||
|
||||
hubIdx[sliceType][subName] = subItem
|
||||
}
|
||||
|
||||
// propagate the state of sub-items to set
|
||||
if subItem.Tainted {
|
||||
v.Tainted = true
|
||||
return fmt.Errorf("tainted %s %s, tainted", sliceType, subName)
|
||||
}
|
||||
|
||||
if !subItem.Installed && v.Installed {
|
||||
v.Tainted = true
|
||||
return fmt.Errorf("missing %s %s, tainted", sliceType, subName)
|
||||
}
|
||||
|
||||
if !subItem.UpToDate {
|
||||
v.UpToDate = false
|
||||
return fmt.Errorf("outdated %s %s", sliceType, subName)
|
||||
}
|
||||
|
||||
skip := false
|
||||
|
||||
for idx := range subItem.BelongsToCollections {
|
||||
if subItem.BelongsToCollections[idx] == v.Name {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
|
||||
if !skip {
|
||||
subItem.BelongsToCollections = append(subItem.BelongsToCollections, v.Name)
|
||||
}
|
||||
|
||||
hubIdx[sliceType][subName] = subItem
|
||||
|
||||
log.Tracef("checking for %s - tainted:%t uptodate:%t", subName, v.Tainted, v.UpToDate)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,31 +410,31 @@ func SyncDir(hub *csconfig.Hub, dir string) (error, []string) {
|
|||
}
|
||||
}
|
||||
|
||||
for k, v := range hubIdx[COLLECTIONS] {
|
||||
if !v.Installed {
|
||||
for name, item := range hubIdx[COLLECTIONS] {
|
||||
if !item.Installed {
|
||||
continue
|
||||
}
|
||||
|
||||
versionStatus := GetVersionStatus(&v)
|
||||
versionStatus := GetVersionStatus(&item)
|
||||
switch versionStatus {
|
||||
case 0: // latest
|
||||
if err := CollecDepsCheck(&v); err != nil {
|
||||
warnings = append(warnings, fmt.Sprintf("dependency of %s : %s", v.Name, err))
|
||||
hubIdx[COLLECTIONS][k] = v
|
||||
if err := CollecDepsCheck(&item); err != nil {
|
||||
warnings = append(warnings, fmt.Sprintf("dependency of %s : %s", item.Name, err))
|
||||
hubIdx[COLLECTIONS][name] = item
|
||||
}
|
||||
case 1: // not up-to-date
|
||||
warnings = append(warnings, fmt.Sprintf("update for collection %s available (currently:%s, latest:%s)", v.Name, v.LocalVersion, v.Version))
|
||||
warnings = append(warnings, fmt.Sprintf("update for collection %s available (currently:%s, latest:%s)", item.Name, item.LocalVersion, item.Version))
|
||||
default: // version is higher than the highest available from hub?
|
||||
warnings = append(warnings, fmt.Sprintf("collection %s is in the future (currently:%s, latest:%s)", v.Name, v.LocalVersion, v.Version))
|
||||
warnings = append(warnings, fmt.Sprintf("collection %s is in the future (currently:%s, latest:%s)", item.Name, item.LocalVersion, item.Version))
|
||||
}
|
||||
|
||||
log.Debugf("installed (%s) - status:%d | installed:%s | latest : %s | full : %+v", v.Name, versionStatus, v.LocalVersion, v.Version, v.Versions)
|
||||
log.Debugf("installed (%s) - status:%d | installed:%s | latest : %s | full : %+v", item.Name, versionStatus, item.LocalVersion, item.Version, item.Versions)
|
||||
}
|
||||
|
||||
return nil, warnings
|
||||
}
|
||||
|
||||
// Updates the infos from HubInit() with the local state
|
||||
// Updates the info from HubInit() with the local state
|
||||
func LocalSync(hub *csconfig.Hub) (error, []string) {
|
||||
skippedLocal = 0
|
||||
skippedTainted = 0
|
||||
|
@ -481,12 +502,12 @@ func LoadPkgIndex(buff []byte) (map[string]map[string]Item, error) {
|
|||
// complete struct
|
||||
log.Tracef("%d item", len(RawIndex[itemType]))
|
||||
|
||||
for idx, item := range RawIndex[itemType] {
|
||||
item.Name = idx
|
||||
for name, item := range RawIndex[itemType] {
|
||||
item.Name = name
|
||||
item.Type = itemType
|
||||
x := strings.Split(item.RemotePath, "/")
|
||||
item.FileName = x[len(x)-1]
|
||||
RawIndex[itemType][idx] = item
|
||||
RawIndex[itemType][name] = item
|
||||
|
||||
if itemType != COLLECTIONS {
|
||||
continue
|
||||
|
|
Loading…
Reference in a new issue