From 407e2c78361313b265e296eb49111441d20fbc59 Mon Sep 17 00:00:00 2001 From: Amit Dsouza Date: Wed, 17 Jul 2024 22:59:25 +1000 Subject: [PATCH] creating yaml-lint cmd Update main.go to call the cobra file --- cmd/yaml-lint/cmd/root.go | 82 +++++++++++++++++++++++++++++++++++++++ cmd/yaml-lint/main.go | 25 ++++++++++++ cmd/yaml-lint/run.sh | 15 +++++++ pkg/yamllint/yamllint.go | 82 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 cmd/yaml-lint/cmd/root.go create mode 100644 cmd/yaml-lint/main.go create mode 100644 cmd/yaml-lint/run.sh create mode 100644 pkg/yamllint/yamllint.go diff --git a/cmd/yaml-lint/cmd/root.go b/cmd/yaml-lint/cmd/root.go new file mode 100644 index 00000000000..425dbdc58ae --- /dev/null +++ b/cmd/yaml-lint/cmd/root.go @@ -0,0 +1,82 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "k8s.io/release/pkg/gcp/build" + "sigs.k8s.io/release-utils/log" +) + +var rootCmd = &cobra.Command{ + Short: "yaml-lint → A tool for linting yaml directories", + Long: `yaml-lint → A tool for linting yaml directories + +This tool lets software developers lint yaml directories. + +`, + Use: "yaml-lint", + SilenceUsage: true, + SilenceErrors: true, + PersistentPreRunE: initLogging, + RunE: func(cmd *cobra.Command, args []string) error { + return run() + }, +} + +type commandLineOptions struct { + directory string +} + +var commandLineOpts = &commandLineOptions{} + +func init() { + rootCmd.PersistentFlags().StringVarP( + &commandLineOpts.directory, + "directory", + "d", + "", + "directory path where yaml files to be linted", + ) +} + +// Execute builds the command. +func Execute() { + if err := rootCmd.Execute(); err != nil { + logrus.Fatal(err) + } +} + +func run() error { + prepareBuildErr := validateYAMLFilesInDirectory(commandLineOpts.directory) + if prepareBuildErr != nil { + return prepareBuildErr + } + + buildErrors := build.RunBuildJobs(buildOpts) + if len(buildErrors) != 0 { + logrus.Fatalf("Failed to run some build jobs: %v", buildErrors) + } + logrus.Info("Finished.") + + return nil +} + +func initLogging(*cobra.Command, []string) error { + return log.SetupGlobalLogger(rootOpts.logLevel) +} diff --git a/cmd/yaml-lint/main.go b/cmd/yaml-lint/main.go new file mode 100644 index 00000000000..79d6f65339a --- /dev/null +++ b/cmd/yaml-lint/main.go @@ -0,0 +1,25 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "k8s.io/release/cmd/publish-release/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/cmd/yaml-lint/run.sh b/cmd/yaml-lint/run.sh new file mode 100644 index 00000000000..4ae16f206dc --- /dev/null +++ b/cmd/yaml-lint/run.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -Eeuo pipefail + +#export directory to scan for yaml linting issues to env var DIR_TO_LINT +YAML_FILES_TO_LINT=$(find $DIR_TO_LINT -type f \( -name "*.yaml" -o -name "*.yml" \)) +if [ -n "$YAML_FILES_TO_LINT" ]; then + echo "Validating yaml files: \n${YAML_FILES_TO_LINT}" + OUTPUT=$(go run ./validate_yaml.go $YAML_FILES_TO_LINT) + if [[ "$OUTPUT" == *"YAML Validation Failed"* ]]; then + echo "Yaml linting issues:" + echo "$OUTPUT" + fi +else + echo "No YAML linting issue for $YAML_FILES_TO_LINT" +fi \ No newline at end of file diff --git a/pkg/yamllint/yamllint.go b/pkg/yamllint/yamllint.go new file mode 100644 index 00000000000..08d7e4e3cbf --- /dev/null +++ b/pkg/yamllint/yamllint.go @@ -0,0 +1,82 @@ +package yamllint + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "sigs.k8s.io/yaml" +) + +// validateYAML reads and parses the YAML file at the given path. +func validateYAML(filePath string) string { + data, err := os.ReadFile(filePath) + if err != nil { + return fmt.Sprintf("Error reading %s:\n%s", filePath, err.Error()) + } + + var content interface{} + if err := yaml.UnmarshalStrict(data, &content); err != nil { + return fmt.Sprintf("Error in %s:\n%s", filePath, err.Error()) + } + + return "Valid" +} + +func FindYAMLFiles(dirPath string) ([]string, error) { + var yamlFiles []string + + err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && (strings.HasSuffix(info.Name(), ".yaml") || strings.HasSuffix(info.Name(), ".yml")) { + yamlFiles = append(yamlFiles, path) + } + return nil + }) + + return yamlFiles, err +} + +// validateYAMLFilesInDirectory finds and validates all YAML files in the given directory. +func validateYAMLFilesInDirectory(dirPath string) { + files, err := FindYAMLFiles(dirPath) + if err != nil { + fmt.Printf("Error finding YAML files in %s:\n%s", dirPath, err.Error()) + return + } + + if len(files) == 0 { + fmt.Println("No YAML files found.") + return + } + invalidFiles := []string{} + for _, file := range files { + result := validateYAML(file) + if result != "Valid" { + invalidFiles = append(invalidFiles, result) + } + } + + if len(invalidFiles) > 0 { + fmt.Println("YAML Validation Failed:\n") + for _, errorMsg := range invalidFiles { + fmt.Println(errorMsg) + fmt.Println("\n" + strings.Repeat("-", 40) + "\n") + } + } else { + fmt.Println("All YAML files are valid.") + } +} + +// func main() { +// if len(os.Args) < 2 { +// fmt.Println("No directory specified.") +// os.Exit(1) +// } + +// dirPath := os.Args[1] +// validateYAMLFilesInDirectory(dirPath) +// }