From c887ec2c3057e5bd84e8345f7e77c05b776df2bd Mon Sep 17 00:00:00 2001 From: Julien Jourdain Date: Fri, 30 Jun 2023 16:15:49 +0200 Subject: [PATCH 1/3] feat(profile): add --- checks/profile.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/iterate.go | 41 ---------------- cmd/profile.go | 35 ++++++++++++++ 3 files changed, 155 insertions(+), 41 deletions(-) create mode 100644 checks/profile.go delete mode 100644 cmd/iterate.go create mode 100644 cmd/profile.go diff --git a/checks/profile.go b/checks/profile.go new file mode 100644 index 00000000..4316fd14 --- /dev/null +++ b/checks/profile.go @@ -0,0 +1,120 @@ +package checks + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/spf13/viper" +) + +type Layer struct { + Name string + FullPath string + InitStatus bool + RefreshTime int +} + +func RunProfileCheck() { + layers, _ := GetLayers() + for _, layer := range layers { + fmt.Println("Initializing layer", layer.FullPath) + err := layer.Init() + if err != nil { + panic(err) + } + err = layer.GetRefreshTime() + if err != nil { + panic(err) + } + } +} + +func GetLayers() ([]Layer, error) { + root := viper.GetString("codebase-path") // Root directory to start browsing from + layers := []Layer{} + + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Check if the current path is a file and its name matches "terragrunt.hcl" + if !info.IsDir() && info.Name() == "terragrunt.hcl" { + layers = append(layers, Layer{Name: path[len(root) : len(path)-len(info.Name())-1], FullPath: path[:len(path)-len(info.Name())-1]}) + } + + return nil + }) + + if err != nil { + fmt.Println("Error:", err) + } + return layers, nil +} + +// Function to initialize a layer (terragrunt) +func (l *Layer) Init() error { + // Create the terragrunt command + terragruntCmd := exec.Command("terragrunt", "init") + + // Set the command's working directory to the Terragrunt configuration directory + terragruntCmd.Dir = l.FullPath + + // Redirect the command's output to the standard output + terragruntCmd.Stdout = os.Stdout + terragruntCmd.Stderr = os.Stderr + + // Run the terragrunt command + err := terragruntCmd.Run() + if err != nil { + return err + } + + l.InitStatus = true + + return nil +} + +// Function to generate a layer plan using terragrunt +func (l *Layer) GetRefreshTime() error { + // Create the terragrunt command + terragruntCmd := exec.Command("terragrunt", "state", "list") + + // Set the command's working directory to the Terragrunt configuration directory + terragruntCmd.Dir = l.FullPath + + // Create a pipe to capture the stdout + stdoutPipe, err := terragruntCmd.StdoutPipe() + if err != nil { + return err + } + + // Start the terragrunt command + err = terragruntCmd.Start() + if err != nil { + return err + } + + // Create a scanner to read from the stdout pipe + scanner := bufio.NewScanner(stdoutPipe) + lineCount := 0 + + // Read each line from the stdout and count the number of lines + for scanner.Scan() { + lineCount++ + } + + // Wait for the command to finish + err = terragruntCmd.Wait() + if err != nil { + return err + } + + // Set the refresh time to the number of lines + l.RefreshTime = lineCount + + return nil +} diff --git a/cmd/iterate.go b/cmd/iterate.go deleted file mode 100644 index 9910949d..00000000 --- a/cmd/iterate.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright © 2023 NAME HERE -*/ -package cmd - -import ( - "fmt" - "guacamole/checks" - - "github.com/spf13/cobra" -) - -// iterateCmd represents the iterate command -var iterateCmd = &cobra.Command{ - Use: "iterate", - Short: "A brief description of your command", - Long: `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - Run: func(cmd *cobra.Command, args []string) { - checks.Iterate() - fmt.Println("iterate called") - }, -} - -func init() { - rootCmd.AddCommand(iterateCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // iterateCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // iterateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/cmd/profile.go b/cmd/profile.go new file mode 100644 index 00000000..4cec8f01 --- /dev/null +++ b/cmd/profile.go @@ -0,0 +1,35 @@ +/* +Copyright © 2023 NAME HERE +*/ +package cmd + +import ( + "fmt" + "guacamole/checks" + + "github.com/spf13/cobra" +) + +// profileCmd represents the profile command +var profileCmd = &cobra.Command{ + Use: "profile", + Short: "Estimate the refresh time of your codebase", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("profile called") + checks.RunProfileCheck() + }, +} + +func init() { + rootCmd.AddCommand(profileCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // profileCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // profileCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} From a3e6052c6e30e01306dd8c340d320ff7a61af288 Mon Sep 17 00:00:00 2001 From: Julien Jourdain Date: Fri, 30 Jun 2023 16:26:03 +0200 Subject: [PATCH 2/3] feat(iterate): add --- cmd/iterate.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 cmd/iterate.go diff --git a/cmd/iterate.go b/cmd/iterate.go new file mode 100644 index 00000000..9910949d --- /dev/null +++ b/cmd/iterate.go @@ -0,0 +1,41 @@ +/* +Copyright © 2023 NAME HERE +*/ +package cmd + +import ( + "fmt" + "guacamole/checks" + + "github.com/spf13/cobra" +) + +// iterateCmd represents the iterate command +var iterateCmd = &cobra.Command{ + Use: "iterate", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + checks.Iterate() + fmt.Println("iterate called") + }, +} + +func init() { + rootCmd.AddCommand(iterateCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // iterateCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // iterateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} From 16406d6cb18e93518ccc2fc43bffe3a9f6391177 Mon Sep 17 00:00:00 2001 From: Julien Jourdain Date: Fri, 30 Jun 2023 16:44:08 +0200 Subject: [PATCH 3/3] feat(profile): add --- checks/checks.go | 1 + checks/profile.go | 23 ++++++++++++++++++++--- cmd/profile.go | 4 +--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/checks/checks.go b/checks/checks.go index e1d88806..31499429 100644 --- a/checks/checks.go +++ b/checks/checks.go @@ -17,6 +17,7 @@ func Checks() { ProviderInModule, Naming, Iterate, + Profile, } totalChecks := len(listOfChecks) // Displaying the results diff --git a/checks/profile.go b/checks/profile.go index 4316fd14..d4184ae4 100644 --- a/checks/profile.go +++ b/checks/profile.go @@ -3,6 +3,7 @@ package checks import ( "bufio" "fmt" + "guacamole/data" "os" "os/exec" "path/filepath" @@ -17,8 +18,15 @@ type Layer struct { RefreshTime int } -func RunProfileCheck() { - layers, _ := GetLayers() +func Profile() data.Check { + checkStatus := data.Check{ + Name: "Layers' refresh time", + Status: "✅", + RelatedGuidelines: "https://github.com/padok-team/docs-terraform-guidelines/blob/main/terraform/wysiwg_patterns.md", + } + layerInError := []string{} + + layers, _ := getLayers() for _, layer := range layers { fmt.Println("Initializing layer", layer.FullPath) err := layer.Init() @@ -29,10 +37,19 @@ func RunProfileCheck() { if err != nil { panic(err) } + if layer.RefreshTime > 120 { + layerInError = append(layerInError, layer.Name) + } } + + if len(layerInError) > 0 { + checkStatus.Status = "❌" + } + + return checkStatus } -func GetLayers() ([]Layer, error) { +func getLayers() ([]Layer, error) { root := viper.GetString("codebase-path") // Root directory to start browsing from layers := []Layer{} diff --git a/cmd/profile.go b/cmd/profile.go index 4cec8f01..bea10b0c 100644 --- a/cmd/profile.go +++ b/cmd/profile.go @@ -4,7 +4,6 @@ Copyright © 2023 NAME HERE package cmd import ( - "fmt" "guacamole/checks" "github.com/spf13/cobra" @@ -15,8 +14,7 @@ var profileCmd = &cobra.Command{ Use: "profile", Short: "Estimate the refresh time of your codebase", Run: func(cmd *cobra.Command, args []string) { - fmt.Println("profile called") - checks.RunProfileCheck() + checks.Profile() }, }