github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/scripts/juju-inspect/main.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "bufio" 8 "bytes" 9 "flag" 10 "fmt" 11 "io" 12 "log" 13 "os" 14 "path/filepath" 15 16 "github.com/juju/version/v2" 17 "gopkg.in/yaml.v2" 18 19 "github.com/juju/juju/scripts/juju-inspect/rules" 20 ) 21 22 func main() { 23 var includeNested bool 24 var startCountAmount int 25 flag.BoolVar(&includeNested, "include-nested", false, "inlcude nested agents") 26 flag.IntVar(&startCountAmount, "start-count-amount", 3, "number of start counts to show") 27 flag.Parse() 28 29 files := flag.Args() 30 if len(files) == 0 { 31 log.Fatal("expected at least on file") 32 } 33 allRules := []Rule{ 34 rules.NewRaftRule(), 35 rules.NewMongoRule(), 36 rules.NewPubsubRule(), 37 rules.NewManifoldsRule(includeNested), 38 rules.NewStartCountRule(includeNested, startCountAmount), 39 } 40 41 if len(files) == 1 { 42 matches, err := filepath.Glob(files[0]) 43 if err == nil && len(matches) > 0 { 44 files = matches 45 } 46 } 47 48 for _, file := range files { 49 f, err := os.Open(file) 50 if err != nil { 51 log.Fatal(err) 52 } 53 54 // Engine reports aren't actually valid yaml files. Instead they have a 55 // header that isn't a comment! This code exists to skip that line. 56 row1, _, err := bufio.NewReader(f).ReadLine() 57 if err != nil { 58 log.Fatal(err) 59 } 60 61 _, err = f.Seek(int64(len(row1)), io.SeekStart) 62 if err != nil { 63 log.Fatal(err) 64 } 65 66 var report rules.Report 67 if err := yaml.NewDecoder(f).Decode(&report); err != nil { 68 log.Fatal(err) 69 } 70 71 agent := report.Manifolds["agent"] 72 73 var out AgentReport 74 if err := agent.UnmarshalReport(&out); err != nil { 75 log.Fatal(err) 76 } 77 for _, rule := range allRules { 78 if err := rule.Run(out.Agent, report); err != nil { 79 fmt.Printf("Skipping %T, because of error: %v", rule, err) 80 } 81 } 82 } 83 84 fmt.Println("") 85 fmt.Println("Analysis of Engine Report:") 86 fmt.Println("") 87 88 buf := new(bytes.Buffer) 89 for _, rule := range allRules { 90 rule.Write(buf) 91 } 92 fmt.Println(buf) 93 } 94 95 type Rule interface { 96 Run(string, rules.Report) error 97 Write(io.Writer) 98 } 99 100 type AgentReport struct { 101 Agent string `yaml:"agent"` 102 Version version.Number `yaml:"version"` 103 }