forked from toolshed/abra
		
	
		
			
				
	
	
		
			141 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package recipe
 | |
| 
 | |
| import (
 | |
| 	"coopcloud.tech/abra/cli/internal"
 | |
| 	"coopcloud.tech/abra/pkg/autocomplete"
 | |
| 	"coopcloud.tech/abra/pkg/formatter"
 | |
| 	"coopcloud.tech/abra/pkg/lint"
 | |
| 	"coopcloud.tech/abra/pkg/log"
 | |
| 	"github.com/spf13/cobra"
 | |
| )
 | |
| 
 | |
| var RecipeLintCommand = &cobra.Command{
 | |
| 	Use:     "lint <recipe> [flags]",
 | |
| 	Short:   "Lint a recipe",
 | |
| 	Aliases: []string{"l"},
 | |
| 	Args:    cobra.MinimumNArgs(1),
 | |
| 	ValidArgsFunction: func(
 | |
| 		cmd *cobra.Command,
 | |
| 		args []string,
 | |
| 		toComplete string) ([]string, cobra.ShellCompDirective) {
 | |
| 		return autocomplete.RecipeNameComplete()
 | |
| 	},
 | |
| 	Run: func(cmd *cobra.Command, args []string) {
 | |
| 		recipe := internal.ValidateRecipe(args, cmd.Name())
 | |
| 
 | |
| 		if err := recipe.Ensure(internal.GetEnsureContext()); err != nil {
 | |
| 			log.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		headers := []string{
 | |
| 			"ref",
 | |
| 			"rule",
 | |
| 			"severity",
 | |
| 			"satisfied",
 | |
| 			"skipped",
 | |
| 			"resolve",
 | |
| 		}
 | |
| 
 | |
| 		table, err := formatter.CreateTable()
 | |
| 		if err != nil {
 | |
| 			log.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		table.Headers(headers...)
 | |
| 
 | |
| 		hasError := false
 | |
| 		var rows [][]string
 | |
| 		var warnMessages []string
 | |
| 		for level := range lint.LintRules {
 | |
| 			for _, rule := range lint.LintRules[level] {
 | |
| 				if onlyError && rule.Level != "error" {
 | |
| 					log.Debugf("skipping %s, does not have level \"error\"", rule.Ref)
 | |
| 					continue
 | |
| 				}
 | |
| 
 | |
| 				skipped := false
 | |
| 				if rule.Skip(recipe) {
 | |
| 					skipped = true
 | |
| 				}
 | |
| 
 | |
| 				skippedOutput := "-"
 | |
| 				if skipped {
 | |
| 					skippedOutput = "✅"
 | |
| 				}
 | |
| 
 | |
| 				satisfied := false
 | |
| 				if !skipped {
 | |
| 					ok, err := rule.Function(recipe)
 | |
| 					if err != nil {
 | |
| 						warnMessages = append(warnMessages, err.Error())
 | |
| 					}
 | |
| 
 | |
| 					if !ok && rule.Level == "error" {
 | |
| 						hasError = true
 | |
| 					}
 | |
| 
 | |
| 					if ok {
 | |
| 						satisfied = true
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				satisfiedOutput := "✅"
 | |
| 				if !satisfied {
 | |
| 					satisfiedOutput = "❌"
 | |
| 					if skipped {
 | |
| 						satisfiedOutput = "-"
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				row := []string{
 | |
| 					rule.Ref,
 | |
| 					rule.Description,
 | |
| 					rule.Level,
 | |
| 					satisfiedOutput,
 | |
| 					skippedOutput,
 | |
| 					rule.HowToResolve,
 | |
| 				}
 | |
| 
 | |
| 				rows = append(rows, row)
 | |
| 				table.Row(row...)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if len(rows) > 0 {
 | |
| 			if err := formatter.PrintTable(table); err != nil {
 | |
| 				log.Fatal(err)
 | |
| 			}
 | |
| 
 | |
| 			for _, warnMsg := range warnMessages {
 | |
| 				log.Warn(warnMsg)
 | |
| 			}
 | |
| 
 | |
| 			if hasError {
 | |
| 				log.Warnf("critical errors present in %s config", recipe.Name)
 | |
| 			}
 | |
| 		}
 | |
| 	},
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	onlyError bool
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	RecipeLintCommand.Flags().BoolVarP(
 | |
| 		&internal.Chaos,
 | |
| 		"chaos",
 | |
| 		"C",
 | |
| 		false,
 | |
| 		"ignore uncommitted recipes changes",
 | |
| 	)
 | |
| 
 | |
| 	RecipeLintCommand.Flags().BoolVarP(
 | |
| 		&onlyError,
 | |
| 		"error",
 | |
| 		"e",
 | |
| 		false,
 | |
| 		"only show errors",
 | |
| 	)
 | |
| }
 |