github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/imagescan/imgscan.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "log/slog" 7 "net/http" 8 "net/http/pprof" 9 "os" 10 "runtime" 11 12 "github.com/castai/image-analyzer/image/hostfs" 13 "github.com/castai/kvisor/cmd/imagescan/collector" 14 "github.com/castai/kvisor/cmd/imagescan/config" 15 "github.com/castai/kvisor/pkg/blobscache" 16 "github.com/castai/kvisor/pkg/castai" 17 v1 "github.com/google/go-containerregistry/pkg/v1" 18 "github.com/sirupsen/logrus" 19 "github.com/spf13/cobra" 20 ) 21 22 func NewCommand(version string) *cobra.Command { 23 return &cobra.Command{ 24 Use: "scan", 25 Short: "Run kvisor image scanning", 26 Run: func(cmd *cobra.Command, args []string) { 27 if err := run(cmd.Context(), version); err != nil { 28 slog.Error(err.Error()) 29 os.Exit(1) 30 } 31 }, 32 } 33 } 34 35 func run(ctx context.Context, version string) error { 36 // TODO: Switch to pkg/logging. 37 log := logrus.New() 38 log.SetLevel(logrus.DebugLevel) 39 log.Infof("running image scan job, version=%s", version) 40 41 cfg, err := config.FromEnv() 42 if err != nil { 43 return err 44 } 45 46 blobsCache := blobscache.NewRemoteBlobsCacheClient(cfg.BlobsCacheURL) 47 48 ingestClient, err := castai.NewClient(fmt.Sprintf("kvisor-imagescan/%s", version), castai.Config{ 49 ClusterID: cfg.CastaiClusterID, 50 APIKey: cfg.CastaiAPIKey, 51 APIGrpcAddr: cfg.CastaiAPIGrpcAddr, 52 Insecure: cfg.CastaiGRPCInsecure, 53 }) 54 if err != nil { 55 return err 56 } 57 defer ingestClient.Close() 58 59 var h *hostfs.ContainerdHostFSConfig 60 if cfg.Runtime == config.RuntimeContainerd && cfg.Mode == config.ModeHostFS { 61 h = &hostfs.ContainerdHostFSConfig{ 62 Platform: v1.Platform{ 63 Architecture: runtime.GOARCH, 64 OS: runtime.GOOS, 65 }, 66 ContentDir: config.ContainerdContentDir, 67 } 68 } 69 c := collector.New(log, cfg, ingestClient.GRPC, blobsCache, h) 70 71 ctx, cancel := context.WithTimeout(ctx, cfg.Timeout) 72 defer cancel() 73 74 if cfg.PprofAddr != "" { 75 mux := http.NewServeMux() 76 addPprofHandlers(mux) 77 go func() { 78 if err := http.ListenAndServe(cfg.PprofAddr, mux); err != nil { //nolint:gosec 79 log.Warnf("pprof http server failed: %v", err) 80 } 81 }() 82 } 83 84 log.Infof("collecting artifacts for image '%s(%s)', mode=%s", cfg.ImageName, cfg.ImageID, cfg.Mode) 85 err = c.Collect(ctx) 86 if err != nil { 87 return fmt.Errorf("image artifacts collection failed: %w", err) 88 } 89 log.Info("image artifacts collection finished") 90 return nil 91 } 92 93 func addPprofHandlers(mux *http.ServeMux) { 94 mux.HandleFunc("/debug/pprof/", pprof.Index) 95 mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) 96 mux.HandleFunc("/debug/pprof/profile", pprof.Profile) 97 mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) 98 mux.HandleFunc("/debug/pprof/trace", pprof.Trace) 99 }