forked from toolshed/abra
		
	
		
			
				
	
	
		
			150 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package recipe
 | |
| 
 | |
| import (
 | |
| 	"strings"
 | |
| 
 | |
| 	"coopcloud.tech/abra/cli/internal"
 | |
| 	"coopcloud.tech/abra/pkg/autocomplete"
 | |
| 	"coopcloud.tech/abra/pkg/formatter"
 | |
| 	"coopcloud.tech/abra/pkg/i18n"
 | |
| 	"coopcloud.tech/abra/pkg/lint"
 | |
| 	"coopcloud.tech/abra/pkg/log"
 | |
| 	"github.com/spf13/cobra"
 | |
| )
 | |
| 
 | |
| // translators: `abra recipe lint` aliases. use a comma separated list of
 | |
| // aliases with no spaces in between
 | |
| var recipeLintAliases = i18n.G("l")
 | |
| 
 | |
| var RecipeLintCommand = &cobra.Command{
 | |
| 	// translators: `recipe lint` command
 | |
| 	Use: i18n.G("lint <recipe> [flags]"),
 | |
| 	// translators: Short description for `recipe lint` command
 | |
| 	Short:   i18n.G("Lint a recipe"),
 | |
| 	Aliases: strings.Split(recipeLintAliases, ","),
 | |
| 	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{
 | |
| 			i18n.G("ref"),
 | |
| 			i18n.G("rule"),
 | |
| 			i18n.G("severity"),
 | |
| 			i18n.G("satisfied"),
 | |
| 			i18n.G("skipped"),
 | |
| 			i18n.G("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.Debug(i18n.G("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 == i18n.G("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.Warn(i18n.G("critical errors present in %s config", recipe.Name))
 | |
| 			}
 | |
| 		}
 | |
| 	},
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	onlyError bool
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	RecipeLintCommand.Flags().BoolVarP(
 | |
| 		&internal.Chaos,
 | |
| 		i18n.G("chaos"),
 | |
| 		i18n.G("C"),
 | |
| 		false,
 | |
| 		i18n.G("ignore uncommitted recipes changes"),
 | |
| 	)
 | |
| 
 | |
| 	RecipeLintCommand.Flags().BoolVarP(
 | |
| 		&onlyError,
 | |
| 		i18n.G("error"),
 | |
| 		i18n.G("e"),
 | |
| 		false,
 | |
| 		i18n.G("only show errors"),
 | |
| 	)
 | |
| }
 |