github.com/fafucoder/cilium@v1.6.11/cilium/cmd/bpf_sha_list.go (about) 1 // Copyright 2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "strconv" 23 24 "github.com/cilium/cilium/common" 25 "github.com/cilium/cilium/pkg/command" 26 "github.com/cilium/cilium/pkg/defaults" 27 28 "github.com/spf13/cobra" 29 ) 30 31 const ( 32 shaTitle = "Datapath SHA" 33 endpointsTitle = "Endpoint(s)" 34 35 noSHA = "<No template used>" 36 brokenSHA = "<Template path invalid>" 37 ) 38 39 var ( 40 stateDir = filepath.Join(defaults.RuntimePath, defaults.StateDir) 41 templatesDir = filepath.Join(stateDir, defaults.TemplatesDir) 42 43 bpfTemplateListCmd = &cobra.Command{ 44 Use: "list", 45 Aliases: []string{"ls"}, 46 Short: "List BPF template objects.", 47 Run: func(cmd *cobra.Command, args []string) { 48 common.RequireRootPrivilege("cilium bpf sha list") 49 dumpShaList() 50 }, 51 } 52 ) 53 54 func init() { 55 bpfTemplateCmd.AddCommand(bpfTemplateListCmd) 56 command.AddJSONOutput(bpfTemplateListCmd) 57 } 58 59 func isEndpointID(name string) bool { 60 _, err := strconv.Atoi(name) 61 return err == nil 62 } 63 64 // getTemplateSHA returns the SHA that should be reported to the user for 65 // the specified endpoint ID. 66 func getTemplateSHA(epID string) string { 67 // Get symlink from endpointDir 68 templateSymlink := filepath.Join(stateDir, epID, defaults.TemplatePath) 69 f, err := os.Lstat(templateSymlink) 70 if err != nil { 71 return noSHA 72 } 73 if f.Mode()&os.ModeSymlink == 0 { 74 return brokenSHA 75 } 76 77 template, err := os.Readlink(templateSymlink) 78 if err != nil { 79 return brokenSHA 80 } 81 if f, err = os.Stat(template); err != nil { 82 return brokenSHA 83 } 84 return filepath.Base(filepath.Dir(template)) 85 } 86 87 func dumpShaList() { 88 bpfTemplateList := make(map[string][]string) 89 90 // Find all templates 91 templateDirs, err := ioutil.ReadDir(templatesDir) 92 if err != nil { 93 Fatalf("failed to list template directory: %s\n", err) 94 } 95 for _, d := range templateDirs { 96 bpfTemplateList[d.Name()] = []string{} 97 } 98 99 // Find all endpoint usage of the templates 100 stateDirs, err := ioutil.ReadDir(stateDir) 101 if err != nil { 102 Fatalf("failed to list state directory: %s\n", err) 103 } 104 for _, d := range stateDirs { 105 if d.IsDir() && isEndpointID(d.Name()) { 106 epID := d.Name() 107 sha := getTemplateSHA(epID) 108 bpfTemplateList[sha] = append(bpfTemplateList[sha], epID) 109 } 110 } 111 112 if command.OutputJSON() { 113 if err := command.PrintOutput(bpfTemplateList); err != nil { 114 Fatalf("error getting output of map in JSON: %s\n", err) 115 } 116 return 117 } 118 119 // Mark unused templates with a "-" in text output 120 for sha, eps := range bpfTemplateList { 121 if len(eps) == 0 { 122 bpfTemplateList[sha] = []string{"-"} 123 } 124 } 125 if len(bpfTemplateList) == 0 { 126 fmt.Fprintf(os.Stderr, "No entries found.\n") 127 } else { 128 TablePrinter(shaTitle, endpointsTitle, bpfTemplateList) 129 } 130 }