-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
16fee00
commit 62da24f
Showing
10 changed files
with
1,174 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2021 Contributors to the Veraison project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cmd | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var comidCmd = &cobra.Command{ | ||
Use: "comid", | ||
Short: "CoMID specific manipulation", | ||
Long: `CoMID specific manipulation | ||
Create CoMID from template t1.json and save the result in the current working directory. | ||
cli comid create --file=t1.json | ||
`, | ||
|
||
Run: func(cmd *cobra.Command, args []string) { | ||
if len(args) == 0 { | ||
cmd.Help() // nolint: errcheck | ||
os.Exit(0) | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(comidCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// Copyright 2021 Contributors to the Veraison project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cmd | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/spf13/afero" | ||
"github.com/spf13/cobra" | ||
"github.com/veraison/corim/comid" | ||
) | ||
|
||
var ( | ||
comidCreateFiles []string | ||
comidCreateDirs []string | ||
comidCreateOutputDir string | ||
) | ||
|
||
var comidCreateCmd = NewComidCreateCmd() | ||
|
||
func NewComidCreateCmd() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "create", | ||
Short: "create one or more CBOR-encoded CoMID(s) from the supplied JSON template(s)", | ||
Long: `create one or more CBOR-encoded CoMID(s) from the supplied JSON template(s) | ||
Create CoMIDs from templates t1.json and t2.json, plus any template found in the | ||
templates/ directory. Save them to the current working directory. | ||
cli comid create --tmpl-file=t1.json --tmpl-file=t2.json --tmpl-dir=templates | ||
Create one CoMID from template t3.json and save it to the comids/ directory. | ||
Note that the output directory must exist. | ||
cli comid create --tmpl-file=t3.json --output-dir=comids | ||
`, | ||
|
||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if err := checkComidCreateArgs(); err != nil { | ||
return err | ||
} | ||
|
||
filesList := filesList(comidCreateFiles, comidCreateDirs) | ||
if len(filesList) == 0 { | ||
return errors.New("no files found") | ||
} | ||
|
||
for _, tmplFile := range filesList { | ||
cborFile, err := templateToCBOR(tmplFile, comidCreateOutputDir) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("created %q from %q\n", cborFile, tmplFile) | ||
} | ||
return nil | ||
}, | ||
} | ||
|
||
cmd.Flags().StringArrayVarP( | ||
&comidCreateFiles, "tmpl-file", "f", []string{}, "a CoMID template file (in JSON format)", | ||
) | ||
|
||
cmd.Flags().StringArrayVarP( | ||
&comidCreateDirs, "tmpl-dir", "d", []string{}, "a directory containing CoMID template files", | ||
) | ||
|
||
cmd.Flags().StringVarP( | ||
&comidCreateOutputDir, "output-dir", "o", ".", "directory where the created files are stored", | ||
) | ||
|
||
return cmd | ||
} | ||
|
||
func checkComidCreateArgs() error { | ||
if len(comidCreateFiles) == 0 && len(comidCreateDirs) == 0 { | ||
return errors.New("no templates supplied") | ||
} | ||
return nil | ||
} | ||
|
||
func filesList(files, dirs []string) []string { | ||
var l []string | ||
|
||
for _, file := range files { | ||
if _, err := fs.Stat(file); err == nil { | ||
l = append(l, file) | ||
} | ||
} | ||
|
||
for _, dir := range dirs { | ||
filesInfo, err := afero.ReadDir(fs, dir) | ||
if err != nil { | ||
continue | ||
} | ||
|
||
for _, fileInfo := range filesInfo { | ||
if !fileInfo.IsDir() && filepath.Ext(fileInfo.Name()) == ".json" { | ||
l = append(l, filepath.Join(dir, fileInfo.Name())) | ||
} | ||
} | ||
} | ||
|
||
return l | ||
} | ||
|
||
func templateToCBOR(tmplFile, outputDir string) (string, error) { | ||
var ( | ||
tmplData, cborData []byte | ||
cborFile string | ||
c comid.Comid | ||
err error | ||
) | ||
|
||
if tmplData, err = afero.ReadFile(fs, tmplFile); err != nil { | ||
return "", fmt.Errorf("error loading template from %s: %w", tmplFile, err) | ||
} | ||
|
||
if err = c.FromJSON(tmplData); err != nil { | ||
return "", fmt.Errorf("error decoding template from %s: %w", tmplFile, err) | ||
} | ||
|
||
if err = c.Valid(); err != nil { | ||
return "", fmt.Errorf("error validating template %s: %w", tmplFile, err) | ||
} | ||
|
||
cborData, err = c.ToCBOR() | ||
if err != nil { | ||
return "", fmt.Errorf("error encoding template %s to CBOR: %w", tmplFile, err) | ||
} | ||
|
||
// we can use tag-id as the basename, since it is supposedly unique | ||
cborFile = filepath.Join(outputDir, c.TagIdentity.TagID.String()+".cbor") | ||
|
||
err = afero.WriteFile(fs, cborFile, cborData, 0400) | ||
if err != nil { | ||
return "", fmt.Errorf("error saving CBOR file %s: %w", cborFile, err) | ||
} | ||
|
||
return cborFile, nil | ||
} | ||
|
||
func init() { | ||
comidCmd.AddCommand(comidCreateCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright 2021 Contributors to the Veraison project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cmd | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/spf13/afero" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"github.com/veraison/corim/comid" | ||
) | ||
|
||
func Test_ComidCreateCmd_unknown_argument(t *testing.T) { | ||
cmd := NewComidCreateCmd() | ||
|
||
args := []string{"--unknown-argument=val"} | ||
cmd.SetArgs(args) | ||
|
||
err := cmd.Execute() | ||
assert.EqualError(t, err, "unknown flag: --unknown-argument") | ||
} | ||
|
||
func Test_ComidCreateCmd_no_templates(t *testing.T) { | ||
cmd := NewComidCreateCmd() | ||
|
||
// no args | ||
|
||
err := cmd.Execute() | ||
assert.EqualError(t, err, "no templates supplied") | ||
} | ||
|
||
func Test_ComidCreateCmd_no_files_found(t *testing.T) { | ||
cmd := NewComidCreateCmd() | ||
|
||
args := []string{ | ||
"--tmpl-file=unknown", | ||
"--tmpl-dir=unsure", | ||
} | ||
cmd.SetArgs(args) | ||
|
||
err := cmd.Execute() | ||
assert.EqualError(t, err, "no files found") | ||
} | ||
|
||
func Test_ComidCreateCmd_template_with_invalid_json(t *testing.T) { | ||
var err error | ||
|
||
cmd := NewComidCreateCmd() | ||
|
||
fs = afero.NewMemMapFs() | ||
err = afero.WriteFile(fs, "invalid.json", []byte("..."), 0400) | ||
require.NoError(t, err) | ||
|
||
args := []string{ | ||
"--tmpl-file=invalid.json", | ||
} | ||
cmd.SetArgs(args) | ||
|
||
err = cmd.Execute() | ||
assert.EqualError(t, err, "error decoding template from invalid.json: invalid character '.' looking for beginning of value") | ||
} | ||
|
||
func Test_ComidCreateCmd_template_with_invalid_comid(t *testing.T) { | ||
var err error | ||
|
||
cmd := NewComidCreateCmd() | ||
|
||
fs = afero.NewMemMapFs() | ||
err = afero.WriteFile(fs, "bad-comid.json", []byte("{}"), 0400) | ||
require.NoError(t, err) | ||
|
||
args := []string{ | ||
"--tmpl-file=bad-comid.json", | ||
} | ||
cmd.SetArgs(args) | ||
|
||
err = cmd.Execute() | ||
assert.EqualError(t, err, "error validating template bad-comid.json: tag-identity validation failed: empty tag-id") | ||
} | ||
|
||
func Test_ComidCreateCmd_template_from_file_ok(t *testing.T) { | ||
var err error | ||
|
||
cmd := NewComidCreateCmd() | ||
|
||
fs = afero.NewMemMapFs() | ||
err = afero.WriteFile(fs, "ok.json", []byte(comid.PSARefValJSONTemplate), 0400) | ||
require.NoError(t, err) | ||
|
||
args := []string{ | ||
"--tmpl-file=ok.json", | ||
} | ||
cmd.SetArgs(args) | ||
|
||
err = cmd.Execute() | ||
assert.NoError(t, err) | ||
} | ||
|
||
func Test_ComidCreateCmd_template_from_dir_ok(t *testing.T) { | ||
var err error | ||
|
||
cmd := NewComidCreateCmd() | ||
|
||
fs = afero.NewMemMapFs() | ||
err = afero.WriteFile(fs, "testdir/ok.json", []byte(comid.PSARefValJSONTemplate), 0400) | ||
require.NoError(t, err) | ||
|
||
args := []string{ | ||
"--tmpl-dir=testdir", | ||
} | ||
cmd.SetArgs(args) | ||
|
||
err = cmd.Execute() | ||
assert.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright 2021 Contributors to the Veraison project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/afero" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
var ( | ||
cfgFile string | ||
fs = afero.NewOsFs() | ||
) | ||
|
||
// rootCmd represents the base command when called without any subcommands | ||
var rootCmd = &cobra.Command{ | ||
Use: "cli", | ||
Short: "CoRIM & CoMID swiss-army knife", | ||
Version: "0.0.1", | ||
SilenceUsage: true, | ||
SilenceErrors: true, | ||
} | ||
|
||
func Execute() { | ||
cobra.CheckErr(rootCmd.Execute()) | ||
} | ||
|
||
func init() { | ||
cobra.OnInitialize(initConfig) | ||
|
||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cli.yaml)") | ||
} | ||
|
||
// initConfig reads in config file and ENV variables if set | ||
func initConfig() { | ||
if cfgFile != "" { | ||
viper.SetConfigFile(cfgFile) | ||
} else { | ||
home, err := os.UserHomeDir() | ||
cobra.CheckErr(err) | ||
|
||
// search config in home directory with name ".cli" (without extension) | ||
viper.AddConfigPath(home) | ||
viper.SetConfigType("yaml") | ||
viper.SetConfigName(".cli") | ||
} | ||
|
||
viper.AutomaticEnv() // read in environment variables that match | ||
|
||
// if a config file is found, read it in | ||
if err := viper.ReadInConfig(); err == nil { | ||
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) | ||
} | ||
} |
Oops, something went wrong.