refactor: expose kubeconform as a module

This commit is contained in:
Ahmed AbouZaid 2023-04-08 02:51:40 +02:00
parent 16d52804d4
commit 484252d280
4 changed files with 54 additions and 38 deletions

View file

@ -1,4 +1,4 @@
package main package kubeconform
import ( import (
"context" "context"
@ -15,8 +15,6 @@ import (
"github.com/yannh/kubeconform/pkg/validator" "github.com/yannh/kubeconform/pkg/validator"
) )
var version = "development"
func processResults(cancel context.CancelFunc, o output.Output, validationResults <-chan validator.Result, exitOnError bool) <-chan bool { func processResults(cancel context.CancelFunc, o output.Output, validationResults <-chan validator.Result, exitOnError bool) <-chan bool {
success := true success := true
result := make(chan bool) result := make(chan bool)
@ -28,7 +26,7 @@ func processResults(cancel context.CancelFunc, o output.Output, validationResult
} }
if o != nil { if o != nil {
if err := o.Write(res); err != nil { if err := o.Write(res); err != nil {
fmt.Fprint(os.Stderr, "failed writing log\n") log.Fatal("failed writing log: ", err)
} }
} }
if !success && exitOnError { if !success && exitOnError {
@ -46,27 +44,19 @@ func processResults(cancel context.CancelFunc, o output.Output, validationResult
return result return result
} }
func realMain() int { func Validate(cfg config.Config, out string) error {
cfg, out, err := config.FromFlags(os.Args[0], os.Args[1:])
if out != "" { if out != "" {
o := os.Stderr
errCode := 1
if cfg.Help { if cfg.Help {
o = os.Stdout fmt.Fprintln(cfg.Stream.Output, out)
errCode = 0 return nil
} }
fmt.Fprintln(o, out) return fmt.Errorf("config out is not empty")
return errCode
} }
if cfg.Version { if cfg.Version {
fmt.Println(version) fmt.Fprintln(cfg.Stream.Output, out)
return 0 return nil
}
if err != nil {
fmt.Fprintf(os.Stderr, "failed parsing command line: %s\n", err.Error())
return 1
} }
cpuProfileFile := os.Getenv("KUBECONFORM_CPUPROFILE_FILE") cpuProfileFile := os.Getenv("KUBECONFORM_CPUPROFILE_FILE")
@ -93,13 +83,11 @@ func realMain() int {
useStdin = true useStdin = true
} }
var o output.Output o, err := output.New(cfg.Stream.Output, cfg.OutputFormat, cfg.Summary, useStdin, cfg.Verbose)
if o, err = output.New(cfg.OutputFormat, cfg.Summary, useStdin, cfg.Verbose); err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) return fmt.Errorf("failed to get output: %s", err.Error())
return 1
} }
var v validator.Validator v, err := validator.New(cfg.SchemaLocations, validator.Opts{
v, err = validator.New(cfg.SchemaLocations, validator.Opts{
Cache: cfg.Cache, Cache: cfg.Cache,
Debug: cfg.Debug, Debug: cfg.Debug,
SkipTLS: cfg.SkipTLS, SkipTLS: cfg.SkipTLS,
@ -110,8 +98,7 @@ func realMain() int {
IgnoreMissingSchemas: cfg.IgnoreMissingSchemas, IgnoreMissingSchemas: cfg.IgnoreMissingSchemas,
}) })
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) return fmt.Errorf("failed to validate: %s", err.Error())
return 1
} }
validationResults := make(chan validator.Result) validationResults := make(chan validator.Result)
@ -121,7 +108,7 @@ func realMain() int {
var resourcesChan <-chan resource.Resource var resourcesChan <-chan resource.Resource
var errors <-chan error var errors <-chan error
if useStdin { if useStdin {
resourcesChan, errors = resource.FromStream(ctx, "stdin", os.Stdin) resourcesChan, errors = resource.FromStream(ctx, "stdin", cfg.Stream.Input)
} else { } else {
resourcesChan, errors = resource.FromFiles(ctx, cfg.Files, cfg.IgnoreFilenamePatterns) resourcesChan, errors = resource.FromFiles(ctx, cfg.Files, cfg.IgnoreFilenamePatterns)
} }
@ -171,12 +158,8 @@ func realMain() int {
o.Flush() o.Flush()
if !success { if !success {
return 1 return fmt.Errorf("failed to process results")
} }
return 0 return nil
}
func main() {
os.Exit(realMain())
} }

24
main.go Normal file
View file

@ -0,0 +1,24 @@
package main
import (
"fmt"
"os"
"github.com/yannh/kubeconform/cmd/kubeconform"
"github.com/yannh/kubeconform/pkg/config"
)
var version = "development"
func main() {
cfg, out, err := config.FromFlags(os.Args[0], os.Args[1:])
if err != nil {
fmt.Fprintf(os.Stderr, "failed parsing command line: %s\n", err.Error())
os.Exit(1)
}
if err = kubeconform.Validate(cfg, out); err != nil {
fmt.Fprintf(os.Stderr, "failed validating resources: %s - %s\n", err.Error(), out)
os.Exit(1)
}
}

View file

@ -4,9 +4,17 @@ import (
"bytes" "bytes"
"flag" "flag"
"fmt" "fmt"
"io"
"os"
"strings" "strings"
) )
type Stream struct {
Input io.Reader
Output io.Writer
Error io.Writer
}
type Config struct { type Config struct {
Cache string Cache string
Debug bool Debug bool
@ -26,6 +34,7 @@ type Config struct {
IgnoreFilenamePatterns []string IgnoreFilenamePatterns []string
Help bool Help bool
Version bool Version bool
Stream *Stream
} }
type arrayParam []string type arrayParam []string
@ -62,7 +71,9 @@ func FromFlags(progName string, args []string) (Config, string, error) {
c := Config{} c := Config{}
c.Files = []string{} c.Files = []string{}
c.Stream = &Stream{os.Stdin, os.Stdout, os.Stderr}
flags.SetOutput(c.Stream.Output)
flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "master", "version of Kubernetes to validate against, e.g.: 1.18.0") flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "master", "version of Kubernetes to validate against, e.g.: 1.18.0")
flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)") flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds or GVKs to ignore") flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds or GVKs to ignore")

View file

@ -2,7 +2,7 @@ package output
import ( import (
"fmt" "fmt"
"os" "io"
"github.com/yannh/kubeconform/pkg/validator" "github.com/yannh/kubeconform/pkg/validator"
) )
@ -12,9 +12,7 @@ type Output interface {
Flush() error Flush() error
} }
func New(outputFormat string, printSummary, isStdin, verbose bool) (Output, error) { func New(w io.Writer, outputFormat string, printSummary, isStdin, verbose bool) (Output, error) {
w := os.Stdout
switch { switch {
case outputFormat == "json": case outputFormat == "json":
return jsonOutput(w, printSummary, isStdin, verbose), nil return jsonOutput(w, printSummary, isStdin, verbose), nil