From b80f805489c317d83d7fe0b182f3ef5c82a06725 Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Sun, 23 Jul 2023 09:37:32 +0900 Subject: [PATCH] feat: add info command (#2111) --- pkg/cli/info.go | 41 ++++++++++++ pkg/cli/runner.go | 2 + pkg/config/package.go | 1 + pkg/controller/info/info.go | 126 ++++++++++++++++++++++++++++++++++++ pkg/controller/wire.go | 13 ++++ pkg/controller/wire_gen.go | 8 +++ 6 files changed, 191 insertions(+) create mode 100644 pkg/cli/info.go create mode 100644 pkg/controller/info/info.go diff --git a/pkg/cli/info.go b/pkg/cli/info.go new file mode 100644 index 000000000..c3f5c1dc8 --- /dev/null +++ b/pkg/cli/info.go @@ -0,0 +1,41 @@ +package cli + +import ( + "fmt" + + "github.com/aquaproj/aqua/v2/pkg/config" + "github.com/aquaproj/aqua/v2/pkg/controller" + "github.com/urfave/cli/v2" +) + +func (runner *Runner) newInfoCommand() *cli.Command { + return &cli.Command{ + Name: "info", + Usage: "Show information", + Description: `Show information. +e.g. +$ aqua info`, + Action: runner.info, + } +} + +func (runner *Runner) info(c *cli.Context) error { + tracer, err := startTrace(c.String("trace")) + if err != nil { + return err + } + defer tracer.Stop() + + cpuProfiler, err := startCPUProfile(c.String("cpu-profile")) + if err != nil { + return err + } + defer cpuProfiler.Stop() + + param := &config.Param{} + if err := runner.setParam(c, "info", param); err != nil { + return fmt.Errorf("parse the command line arguments: %w", err) + } + ctrl := controller.InitializeInfoCommandController(c.Context, param, runner.Runtime) + return ctrl.Info(c.Context, runner.LogE, param, c.Args().First()) //nolint:wrapcheck +} diff --git a/pkg/cli/runner.go b/pkg/cli/runner.go index d1b8b3f4f..eef0db613 100644 --- a/pkg/cli/runner.go +++ b/pkg/cli/runner.go @@ -56,6 +56,7 @@ func (runner *Runner) setParam(c *cli.Context, commandName string, param *config param.File = c.String("f") param.LogColor = os.Getenv("AQUA_LOG_COLOR") param.AQUAVersion = runner.LDFlags.Version + param.AquaCommitHash = runner.LDFlags.Commit param.RootDir = config.GetRootDir(osenv.New()) homeDir, _ := os.UserHomeDir() param.HomeDir = homeDir @@ -155,6 +156,7 @@ func (runner *Runner) Run(ctx context.Context, args ...string) error { EnableBashCompletion: true, Commands: []*cli.Command{ runner.newInitCommand(), + runner.newInfoCommand(), runner.newInitPolicyCommand(), runner.newPolicyCommand(), runner.newInstallCommand(), diff --git a/pkg/config/package.go b/pkg/config/package.go index 3e2e053cf..019ce6aa7 100644 --- a/pkg/config/package.go +++ b/pkg/config/package.go @@ -218,6 +218,7 @@ type Param struct { LogLevel string File string AQUAVersion string + AquaCommitHash string RootDir string PWD string InsertFile string diff --git a/pkg/controller/info/info.go b/pkg/controller/info/info.go new file mode 100644 index 000000000..a47ec7200 --- /dev/null +++ b/pkg/controller/info/info.go @@ -0,0 +1,126 @@ +package info + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/user" + "runtime" + "strings" + + "github.com/aquaproj/aqua/v2/pkg/config" + rt "github.com/aquaproj/aqua/v2/pkg/runtime" + "github.com/sirupsen/logrus" + "github.com/spf13/afero" +) + +type Controller struct { + fs afero.Fs + finder ConfigFinder + rt *rt.Runtime +} + +func New(fs afero.Fs, finder ConfigFinder, rt *rt.Runtime) *Controller { + return &Controller{ + fs: fs, + finder: finder, + rt: rt, + } +} + +type Info struct { + Version string `json:"version"` + CommitHash string `json:"commit_hash"` + OS string `json:"os"` + Arch string `json:"arch"` + AquaGOOS string `json:"aqua_goos,omitempty"` + AquaGOARCH string `json:"aqua_goarch,omitempty"` + PWD string `json:"pwd"` + RootDir string `json:"root_dir"` + Env map[string]string `json:"env"` + ConfigFiles []*Config `json:"config_files"` +} + +type Config struct { + Path string `json:"path"` +} + +func maskUser(s, username string) string { + return strings.ReplaceAll(s, username, "(USER)") +} + +func (ctrl *Controller) Info(ctx context.Context, logE *logrus.Entry, param *config.Param, cfgFilePath string) error { //nolint:funlen + currentUser, err := user.Current() + if err != nil { + return fmt.Errorf("get a current user: %w", err) + } + userName := currentUser.Username + + filePaths := ctrl.finder.Finds(param.PWD, param.ConfigFilePath) + cfgs := make([]*Config, len(filePaths)) + for i, filePath := range filePaths { + cfgs[i] = &Config{ + Path: maskUser(filePath, userName), + } + } + + info := &Info{ + Version: param.AQUAVersion, + CommitHash: param.AquaCommitHash, + PWD: maskUser(param.PWD, userName), + OS: runtime.GOOS, + Arch: runtime.GOARCH, + RootDir: maskUser(param.RootDir, userName), + ConfigFiles: cfgs, + Env: map[string]string{}, + } + + if ctrl.rt.GOOS != runtime.GOOS { + info.AquaGOOS = ctrl.rt.GOOS + } + if ctrl.rt.GOARCH != runtime.GOARCH { + info.AquaGOARCH = ctrl.rt.GOARCH + } + + envs := []string{ + "AQUA_CONFIG", + "AQUA_DISABLE_LAZY_INSTALL", + "AQUA_DISABLE_POLICY", + "AQUA_EXPERIMENTAL_X_SYS_EXEC", + "AQUA_GENERATE_WITH_DETAIL", + "AQUA_GLOBAL_CONFIG", + "AQUA_GOARCH", + "AQUA_GOOS", + "AQUA_LOG_COLOR", + "AQUA_LOG_LEVEL", + "AQUA_MAX_PARALLELISM", + "AQUA_POLICY_CONFIG", + "AQUA_PROGRESS_BAR", + "AQUA_REQUIRE_CHECKSUM", + "AQUA_ROOT_DIR", + "AQUA_X_SYS_EXEC", + } + for _, envName := range envs { + if v, ok := os.LookupEnv(envName); ok { + info.Env[envName] = maskUser(v, userName) + } + } + if _, ok := os.LookupEnv("AQUA_GITHUB_TOKEN"); ok { + info.Env["AQUA_GITHUB_TOKEN"] = "(masked)" + } else if _, ok := os.LookupEnv("GITHUB_TOKEN"); ok { + info.Env["GITHUB_TOKEN"] = "(masked)" + } + + encoder := json.NewEncoder(os.Stdout) + encoder.SetIndent("", " ") + if err := encoder.Encode(info); err != nil { + return fmt.Errorf("encode info as JSON and output it to stdout: %w", err) + } + return nil +} + +type ConfigFinder interface { + Find(wd, configFilePath string, globalConfigFilePaths ...string) (string, error) + Finds(wd, configFilePath string) []string +} diff --git a/pkg/controller/wire.go b/pkg/controller/wire.go index 1e82bb86d..3a0f62918 100644 --- a/pkg/controller/wire.go +++ b/pkg/controller/wire.go @@ -20,6 +20,7 @@ import ( "github.com/aquaproj/aqua/v2/pkg/controller/generate" genrgst "github.com/aquaproj/aqua/v2/pkg/controller/generate-registry" "github.com/aquaproj/aqua/v2/pkg/controller/generate/output" + "github.com/aquaproj/aqua/v2/pkg/controller/info" "github.com/aquaproj/aqua/v2/pkg/controller/initcmd" "github.com/aquaproj/aqua/v2/pkg/controller/initpolicy" "github.com/aquaproj/aqua/v2/pkg/controller/install" @@ -731,3 +732,15 @@ func InitializeDenyPolicyCommandController(ctx context.Context, param *config.Pa ) return &denypolicy.Controller{} } + +func InitializeInfoCommandController(ctx context.Context, param *config.Param, rt *runtime.Runtime) *info.Controller { + wire.Build( + info.New, + wire.NewSet( + finder.NewConfigFinder, + wire.Bind(new(info.ConfigFinder), new(*finder.ConfigFinder)), + ), + afero.NewOsFs, + ) + return &info.Controller{} +} diff --git a/pkg/controller/wire_gen.go b/pkg/controller/wire_gen.go index f3aafffb8..c7f4cb1b8 100644 --- a/pkg/controller/wire_gen.go +++ b/pkg/controller/wire_gen.go @@ -20,6 +20,7 @@ import ( "github.com/aquaproj/aqua/v2/pkg/controller/generate" "github.com/aquaproj/aqua/v2/pkg/controller/generate-registry" "github.com/aquaproj/aqua/v2/pkg/controller/generate/output" + "github.com/aquaproj/aqua/v2/pkg/controller/info" "github.com/aquaproj/aqua/v2/pkg/controller/initcmd" "github.com/aquaproj/aqua/v2/pkg/controller/initpolicy" "github.com/aquaproj/aqua/v2/pkg/controller/install" @@ -271,3 +272,10 @@ func InitializeDenyPolicyCommandController(ctx context.Context, param *config.Pa controller := denypolicy.New(fs, configFinderImpl, validatorImpl) return controller } + +func InitializeInfoCommandController(ctx context.Context, param *config.Param, rt *runtime.Runtime) *info.Controller { + fs := afero.NewOsFs() + configFinder := finder.NewConfigFinder(fs) + controller := info.New(fs, configFinder, rt) + return controller +}