Skip to content

Commit

Permalink
fix: remove double printing of errors and supress usage text when err…
Browse files Browse the repository at this point in the history
…ors are present after parsing

Signed-off-by: Ben Meier <[email protected]>
  • Loading branch information
astromechza committed Feb 27, 2024
1 parent c507418 commit 36f7261
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 41 deletions.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,25 @@ score-compose run -f /tmp/score.yaml -o /tmp/compose.yaml
- `-f` is the path to the Score file.
- `-o` specifies the path to the output file.

If you're just getting started, follow [this guide](https://docs.score.dev/docs/get-started/score-compose-hello-world/) to run your first Hello World program with `score-compose`.
If you're just getting started, follow [this guide](https://docs.score.dev/docs/get-started/score-compose-hello-world/) to run your first Hello World program with `score-compose`. The full usage of the `run` command is:

```
Translate the SCORE file to docker-compose configuration
Usage:
score-compose run [--file=score.yaml] [--output=compose.yaml] [flags]
Flags:
--build string Replaces 'image' name with compose 'build' instruction
--env-file string Location to store sample .env file
-f, --file string Source SCORE file (default "./score.yaml")
-h, --help help for run
-o, --output string Output file
--overrides string Overrides SCORE file (default "./overrides.score.yaml")
-p, --property stringArray Overrides selected property value
--skip-validation DEPRECATED: Disables Score file schema validation
--verbose Enable diagnostic messages (written to STDERR)
```

## ![Get involved](docs/images/get-involved.svg) Get involved

Expand Down
2 changes: 1 addition & 1 deletion cmd/score-compose/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

func main() {
if err := command.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
_, _ = fmt.Fprintln(os.Stderr, "Error: "+err.Error())
os.Exit(1)
}
}
2 changes: 1 addition & 1 deletion e2e-tests/resources/outputs/run --help-output.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Translate the SCORE file to docker-compose configuration

Usage:
score-compose run [flags]
score-compose run [--file=score.yaml] [--output=compose.yaml] [flags]

Flags:
--build string Replaces 'image' name with compose 'build' instruction
Expand Down
18 changes: 1 addition & 17 deletions e2e-tests/resources/outputs/run --verbose-output.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
'./score.yaml'...
Error: open ./score.yaml: no such file or directory
Usage:
score-compose run [flags]

Flags:
--build string Replaces 'image' name with compose 'build' instruction
--env-file string Location to store sample .env file
-f, --file string Source SCORE file (default "./score.yaml")
-h, --help help for run
-o, --output string Output file
--overrides string Overrides SCORE file (default "./overrides.score.yaml")
-p, --property stringArray Overrides selected property value
--skip-validation DEPRECATED: Disables Score file schema validation
--verbose Enable diagnostic messages (written to STDERR)

open ./score.yaml: no such file or directory
Error: open ./score.yaml: no such file or directory
17 changes: 1 addition & 16 deletions e2e-tests/resources/outputs/run-output.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
Error: open ./score.yaml: no such file or directory
Usage:
score-compose run [flags]

Flags:
--build string Replaces 'image' name with compose 'build' instruction
--env-file string Location to store sample .env file
-f, --file string Source SCORE file (default "./score.yaml")
-h, --help help for run
-o, --output string Output file
--overrides string Overrides SCORE file (default "./overrides.score.yaml")
-p, --property stringArray Overrides selected property value
--skip-validation DEPRECATED: Disables Score file schema validation
--verbose Enable diagnostic messages (written to STDERR)

open ./score.yaml: no such file or directory
Error: open ./score.yaml: no such file or directory
4 changes: 1 addition & 3 deletions e2e-tests/resources/outputs/unknown-output.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
Error: unknown command "unknown" for "score-compose"
Run 'score-compose --help' for usage.
unknown command "unknown" for "score-compose"
Error: unknown command "unknown" for "score-compose"
2 changes: 2 additions & 0 deletions internal/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ var (
This tool produces a docker-compose configuration file from the SCORE specification.
Complete documentation is available at https://score.dev`,
Version: fmt.Sprintf("%s (build: %s; sha: %s)", version.Version, version.BuildTime, version.GitSHA),
// don't print the errors - we print these ourselves in main()
SilenceErrors: true,
}
)

Expand Down
9 changes: 7 additions & 2 deletions internal/command/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,17 @@ func init() {
}

var runCmd = &cobra.Command{
Use: "run",
Use: "run [--file=score.yaml] [--output=compose.yaml]",
Short: "Translate the SCORE file to docker-compose configuration",
RunE: run,
// don't print the errors - we print these ourselves in main()
SilenceErrors: true,
}

func run(cmd *cobra.Command, args []string) error {
// Silence usage message if args are parsed correctly
cmd.SilenceUsage = true

if !verbose {
log.SetOutput(io.Discard)
}
Expand Down Expand Up @@ -185,7 +190,7 @@ func run(cmd *cobra.Command, args []string) error {

// Open output file (optional)
//
var dest = io.Writer(os.Stdout)
var dest = cmd.OutOrStdout()
if outFile != "" {
log.Printf("Creating '%s'...\n", outFile)
destFile, err := os.Create(outFile)
Expand Down
148 changes: 148 additions & 0 deletions internal/command/run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package command

import (
"bytes"
"context"
"os"
"path/filepath"
"testing"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

// executeAndResetCommand is a test helper that runs and then resets a command for executing in another test.
func executeAndResetCommand(ctx context.Context, cmd *cobra.Command, args []string) (string, string, error) {
beforeOut, beforeErr := cmd.OutOrStderr(), cmd.ErrOrStderr()
defer func() {
cmd.SetOut(beforeOut)
cmd.SetErr(beforeErr)
}()

nowOut, nowErr := new(bytes.Buffer), new(bytes.Buffer)
cmd.SetOut(nowOut)
cmd.SetErr(nowErr)
cmd.SetArgs(args)
subCmd, err := cmd.ExecuteContextC(ctx)
if subCmd != nil {
subCmd.SetContext(nil)
subCmd.SilenceUsage = false
subCmd.SilenceErrors = false
subCmd.Flags().VisitAll(func(f *pflag.Flag) {
_ = f.Value.Set(f.DefValue)
})
}
return nowOut.String(), nowErr.String(), err
}

func TestExample(t *testing.T) {
td := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(td, "score.yaml"), []byte(`
apiVersion: score.dev/v1b1
metadata:
name: example-workload-name123
extra-key: extra-value
service:
ports:
port-one:
port: 1000
protocol: TCP
targetPort: 10000
port-two2:
port: 8000
containers:
container-one1:
image: localhost:4000/repo/my-image:tag
command: ["/bin/sh", "-c"]
args: ["hello", "world"]
resources:
requests:
cpu: 1000m
memory: 10Gi
limits:
cpu: "0.24"
memory: 128M
variables:
SOME_VAR: some content here
volumes:
- source: volume-name
target: /mnt/something
readOnly: false
- source: volume-two
target: /mnt/something-else
livenessProbe:
httpGet:
port: 8080
path: /livez
readinessProbe:
httpGet:
host: 127.0.0.1
port: 80
scheme: HTTP
path: /readyz
httpHeaders:
- name: SOME_HEADER
value: some-value-here
container-two2:
image: localhost:4000/repo/my-image:tag
resources:
resource-one1:
metadata:
annotations:
Default-Annotation: this is my annotation
prefix.com/Another-Key_Annotation.2: something else
extra-key: extra-value
type: Resource-One
class: default
params:
extra:
data: here
resource-two2:
type: Resource-Two
`), 0600))
stdout, stderr, err := executeAndResetCommand(context.Background(), rootCmd, []string{"run", "--file", filepath.Join(td, "score.yaml"), "--output", filepath.Join(td, "compose.yaml")})
assert.NoError(t, err)
assert.NotEqual(t, "", stdout)
assert.Equal(t, "", stderr)
rawComposeContent, err := os.ReadFile(filepath.Join(td, "compose.yaml"))
require.NoError(t, err)
var actualComposeContent map[string]interface{}
assert.NoError(t, yaml.Unmarshal(rawComposeContent, &actualComposeContent))
assert.Equal(t, map[string]interface{}{
"services": map[string]interface{}{
"example-workload-name123-container-one1": map[string]interface{}{
"image": "localhost:4000/repo/my-image:tag",
"entrypoint": []interface{}{"/bin/sh", "-c"},
"command": []interface{}{"hello", "world"},
"environment": map[string]interface{}{
"SOME_VAR": "some content here",
},
"ports": []interface{}{
map[string]interface{}{"target": 10000, "published": "1000", "protocol": "TCP"},
map[string]interface{}{"target": 8000, "published": "8000"},
},
"volumes": []interface{}{
map[string]interface{}{"type": "volume", "source": "volume-name", "target": "/mnt/something"},
map[string]interface{}{"type": "volume", "source": "volume-two", "target": "/mnt/something-else"},
},
},
"example-workload-name123-container-two2": map[string]interface{}{
"image": "localhost:4000/repo/my-image:tag",
"network_mode": "service:example-workload-name123-container-one1",
},
},
}, actualComposeContent)
}

func TestExample_invalid_spec(t *testing.T) {
td := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(td, "score.yaml"), []byte(`
{}`), 0600))
stdout, stderr, err := executeAndResetCommand(context.Background(), rootCmd, []string{"run", "--file", filepath.Join(td, "score.yaml"), "--output", filepath.Join(td, "compose.yaml")})
assert.EqualError(t, err, "validating workload spec: jsonschema: '' does not validate with https://score.dev/schemas/score#/required: missing properties: 'apiVersion', 'metadata', 'containers'")
assert.Equal(t, "", stdout)
assert.Equal(t, "", stderr)
}

0 comments on commit 36f7261

Please sign in to comment.