157 lines
3.0 KiB
Go
157 lines
3.0 KiB
Go
package command
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"forge.cadoles.com/wpetit/formidable/internal/def"
|
|
"github.com/pkg/errors"
|
|
"github.com/santhosh-tekuri/jsonschema/v5"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
const (
|
|
filePathPrefix = "@"
|
|
)
|
|
|
|
func commonFlags() []cli.Flag {
|
|
return []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "defaults",
|
|
Aliases: []string{"d"},
|
|
Usage: "Default values as JSON or file path prefixed by '@'",
|
|
Value: "{}",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "values",
|
|
Aliases: []string{"v"},
|
|
Usage: "Current values as JSON or file path prefixed by '@'",
|
|
Value: "{}",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "schema",
|
|
Aliases: []string{"s"},
|
|
Usage: "Use `schema_file` as schema",
|
|
TakesFile: true,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "output",
|
|
Aliases: []string{"o", "out"},
|
|
Value: "-",
|
|
Usage: "Output modified values to `output_file` (or '-' for stdout, the default)",
|
|
},
|
|
}
|
|
}
|
|
|
|
func loadJSONFlag(ctx *cli.Context, flagName string) (interface{}, error) {
|
|
flagValue := ctx.String(flagName)
|
|
|
|
if flagValue == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
if !strings.HasPrefix(flagValue, filePathPrefix) {
|
|
var value interface{}
|
|
|
|
if err := json.Unmarshal([]byte(flagValue), &value); err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
flagValue = strings.TrimPrefix(flagValue, filePathPrefix)
|
|
|
|
file, err := os.Open(flagValue)
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
defer func() {
|
|
if err := file.Close(); err != nil {
|
|
panic(errors.WithStack(err))
|
|
}
|
|
}()
|
|
|
|
reader := json.NewDecoder(file)
|
|
|
|
var values interface{}
|
|
|
|
if err := reader.Decode(&values); err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return values, nil
|
|
}
|
|
|
|
func loadValues(ctx *cli.Context) (interface{}, error) {
|
|
values, err := loadJSONFlag(ctx, "values")
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return values, nil
|
|
}
|
|
|
|
func loadDefaults(ctx *cli.Context) (interface{}, error) {
|
|
values, err := loadJSONFlag(ctx, "defaults")
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return values, nil
|
|
}
|
|
|
|
func loadSchema(ctx *cli.Context) (*jsonschema.Schema, error) {
|
|
schemaFlag := ctx.String("schema")
|
|
|
|
compiler := jsonschema.NewCompiler()
|
|
|
|
compiler.ExtractAnnotations = true
|
|
compiler.AssertFormat = true
|
|
compiler.AssertContent = true
|
|
|
|
var (
|
|
schema *jsonschema.Schema
|
|
err error
|
|
)
|
|
|
|
if schemaFlag == "" {
|
|
schema = def.Schema
|
|
} else {
|
|
schema, err = compiler.Compile(schemaFlag)
|
|
}
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return schema, nil
|
|
}
|
|
|
|
const OutputStdout = "-"
|
|
|
|
type noopWriteCloser struct {
|
|
io.Writer
|
|
}
|
|
|
|
func (c *noopWriteCloser) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func outputWriter(ctx *cli.Context) (io.WriteCloser, error) {
|
|
output := ctx.String("output")
|
|
|
|
if output == OutputStdout {
|
|
return &noopWriteCloser{ctx.App.Writer}, nil
|
|
}
|
|
|
|
file, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE, 0o644)
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
return file, nil
|
|
}
|