remove exit code per error type used by legacy metrics system
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
7c7407672a
commit
23351ece81
@ -44,7 +44,6 @@ import (
|
||||
"github.com/docker/compose/v2/internal/experimental"
|
||||
"github.com/docker/compose/v2/internal/tracing"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
ui "github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/compose/v2/pkg/remote"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
@ -121,17 +120,9 @@ func AdaptCmd(fn CobraCommand) func(cmd *cobra.Command, args []string) error {
|
||||
}()
|
||||
|
||||
err := fn(ctx, cmd, args)
|
||||
var composeErr compose.Error
|
||||
if api.IsErrCanceled(err) || errors.Is(ctx.Err(), context.Canceled) {
|
||||
err = dockercli.StatusError{
|
||||
StatusCode: 130,
|
||||
Status: compose.CanceledStatus,
|
||||
}
|
||||
}
|
||||
if errors.As(err, &composeErr) {
|
||||
err = dockercli.StatusError{
|
||||
StatusCode: composeErr.GetMetricsFailureCategory().ExitCode,
|
||||
Status: err.Error(),
|
||||
}
|
||||
}
|
||||
if ui.Mode == ui.ModeJSON {
|
||||
@ -307,7 +298,7 @@ func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, s
|
||||
|
||||
options, err := o.toProjectOptions(po...)
|
||||
if err != nil {
|
||||
return nil, metrics, compose.WrapComposeError(err)
|
||||
return nil, metrics, err
|
||||
}
|
||||
|
||||
options.WithListeners(func(event string, metadata map[string]any) {
|
||||
@ -339,7 +330,7 @@ func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, s
|
||||
|
||||
project, err := options.LoadProject(ctx)
|
||||
if err != nil {
|
||||
return nil, metrics, compose.WrapComposeError(err)
|
||||
return nil, metrics, err
|
||||
}
|
||||
|
||||
if project.Name == "" {
|
||||
@ -453,7 +444,7 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
|
||||
}
|
||||
_ = cmd.Help()
|
||||
return dockercli.StatusError{
|
||||
StatusCode: compose.CommandSyntaxFailure.ExitCode,
|
||||
StatusCode: 1,
|
||||
Status: fmt.Sprintf("unknown docker command: %q", "compose "+args[0]),
|
||||
}
|
||||
},
|
||||
|
@ -62,7 +62,7 @@ func pluginMain() {
|
||||
|
||||
cmd.SetFlagErrorFunc(func(c *cobra.Command, err error) error {
|
||||
return dockercli.StatusError{
|
||||
StatusCode: compose.CommandSyntaxFailure.ExitCode,
|
||||
StatusCode: 1,
|
||||
Status: err.Error(),
|
||||
}
|
||||
})
|
||||
|
@ -48,7 +48,7 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, service string, op
|
||||
confutil.NewConfig(s.dockerCli),
|
||||
buildx.WithPrefix(p, service, true))
|
||||
if err != nil {
|
||||
return "", WrapCategorisedComposeError(err, BuildFailure)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI 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 compose
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/errdefs"
|
||||
)
|
||||
|
||||
// Error error to categorize failures and extract metrics info
|
||||
type Error struct {
|
||||
Err error
|
||||
Category *FailureCategory
|
||||
}
|
||||
|
||||
// WrapComposeError wraps the error if not nil, otherwise returns nil
|
||||
func WrapComposeError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// WrapCategorisedComposeError wraps the error if not nil, otherwise returns nil
|
||||
func WrapCategorisedComposeError(err error, failure FailureCategory) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return Error{
|
||||
Err: err,
|
||||
Category: &failure,
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrap get underlying error
|
||||
func (e Error) Unwrap() error { return e.Err }
|
||||
|
||||
func (e Error) Error() string { return e.Err.Error() }
|
||||
|
||||
// GetMetricsFailureCategory get metrics status and error code corresponding to this error
|
||||
func (e Error) GetMetricsFailureCategory() FailureCategory {
|
||||
if e.Category != nil {
|
||||
return *e.Category
|
||||
}
|
||||
var pathError *fs.PathError
|
||||
if errors.As(e.Err, &pathError) {
|
||||
return FileNotFoundFailure
|
||||
}
|
||||
if errdefs.IsNotFoundError(e.Err) {
|
||||
return FileNotFoundFailure
|
||||
}
|
||||
return ComposeParseFailure
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI 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 compose
|
||||
|
||||
// FailureCategory struct regrouping metrics failure status and specific exit code
|
||||
type FailureCategory struct {
|
||||
MetricsStatus string
|
||||
ExitCode int
|
||||
}
|
||||
|
||||
const (
|
||||
// APISource is sent for API metrics
|
||||
APISource = "api"
|
||||
// SuccessStatus command success
|
||||
SuccessStatus = "success"
|
||||
// FailureStatus command failure
|
||||
FailureStatus = "failure"
|
||||
// ComposeParseFailureStatus failure while parsing compose file
|
||||
ComposeParseFailureStatus = "failure-compose-parse"
|
||||
// FileNotFoundFailureStatus failure getting compose file
|
||||
FileNotFoundFailureStatus = "failure-file-not-found"
|
||||
// CommandSyntaxFailureStatus failure reading command
|
||||
CommandSyntaxFailureStatus = "failure-cmd-syntax"
|
||||
// BuildFailureStatus failure building image
|
||||
BuildFailureStatus = "failure-build"
|
||||
// PullFailureStatus failure pulling image
|
||||
PullFailureStatus = "failure-pull"
|
||||
// CanceledStatus command canceled
|
||||
CanceledStatus = "canceled"
|
||||
)
|
||||
|
||||
var (
|
||||
// FileNotFoundFailure failure for compose file not found
|
||||
FileNotFoundFailure = FailureCategory{MetricsStatus: FileNotFoundFailureStatus, ExitCode: 14}
|
||||
// ComposeParseFailure failure for composefile parse error
|
||||
ComposeParseFailure = FailureCategory{MetricsStatus: ComposeParseFailureStatus, ExitCode: 15}
|
||||
// CommandSyntaxFailure failure for command line syntax
|
||||
CommandSyntaxFailure = FailureCategory{MetricsStatus: CommandSyntaxFailureStatus, ExitCode: 16}
|
||||
// BuildFailure failure while building images.
|
||||
BuildFailure = FailureCategory{MetricsStatus: BuildFailureStatus, ExitCode: 17}
|
||||
// PullFailure failure while pulling image
|
||||
PullFailure = FailureCategory{MetricsStatus: PullFailureStatus, ExitCode: 18}
|
||||
)
|
||||
|
||||
// ByExitCode retrieve FailureCategory based on command exit code
|
||||
func ByExitCode(exitCode int) FailureCategory {
|
||||
switch exitCode {
|
||||
case 0:
|
||||
return FailureCategory{MetricsStatus: SuccessStatus, ExitCode: 0}
|
||||
case 14:
|
||||
return FileNotFoundFailure
|
||||
case 15:
|
||||
return ComposeParseFailure
|
||||
case 16:
|
||||
return CommandSyntaxFailure
|
||||
case 17:
|
||||
return BuildFailure
|
||||
case 18:
|
||||
return PullFailure
|
||||
case 130:
|
||||
return FailureCategory{MetricsStatus: CanceledStatus, ExitCode: exitCode}
|
||||
default:
|
||||
return FailureCategory{MetricsStatus: FailureStatus, ExitCode: exitCode}
|
||||
}
|
||||
}
|
@ -211,7 +211,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
Text: "Warning",
|
||||
StatusText: getUnwrappedErrorMessage(err),
|
||||
})
|
||||
return "", WrapCategorisedComposeError(err, PullFailure)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -221,7 +221,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
Text: "Error",
|
||||
StatusText: getUnwrappedErrorMessage(err),
|
||||
})
|
||||
return "", WrapCategorisedComposeError(err, PullFailure)
|
||||
return "", err
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(stream)
|
||||
@ -231,10 +231,10 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
return "", WrapCategorisedComposeError(err, PullFailure)
|
||||
return "", err
|
||||
}
|
||||
if jm.Error != nil {
|
||||
return "", WrapCategorisedComposeError(errors.New(jm.Error.Message), PullFailure)
|
||||
return "", errors.New(jm.Error.Message)
|
||||
}
|
||||
if !quietPull {
|
||||
toPullProgressEvent(service.Name, jm, w)
|
||||
|
@ -174,7 +174,7 @@ func TestBuildSSH(t *testing.T) {
|
||||
"--project-directory", "fixtures/build-test/ssh", "build", "--no-cache", "--ssh",
|
||||
"wrong-ssh=./fixtures/build-test/ssh/fake_rsa")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 17,
|
||||
ExitCode: 1,
|
||||
Err: "unset ssh forward key fake-ssh",
|
||||
})
|
||||
})
|
||||
@ -304,7 +304,7 @@ func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) {
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms",
|
||||
"-f", "fixtures/build-test/platforms/compose-unsupported-platform.yml", "build")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 17,
|
||||
ExitCode: 1,
|
||||
Err: "no match for platform in",
|
||||
})
|
||||
})
|
||||
@ -402,7 +402,7 @@ func TestBuildPlatformsStandardErrors(t *testing.T) {
|
||||
t.Run("builder does not support multi-arch", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "build")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 17,
|
||||
ExitCode: 1,
|
||||
Err: `Multi-platform build is not supported for the docker driver.
|
||||
Switch to a different driver, or turn on the containerd image store, and try again.`,
|
||||
})
|
||||
@ -412,7 +412,7 @@ Switch to a different driver, or turn on the containerd image store, and try aga
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms",
|
||||
"-f", "fixtures/build-test/platforms/compose-service-platform-not-in-build-platforms.yaml", "build")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 15,
|
||||
ExitCode: 1,
|
||||
Err: `service.build.platforms MUST include service.platform "linux/riscv64"`,
|
||||
})
|
||||
})
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI 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 e2e
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/icmd"
|
||||
)
|
||||
|
||||
func TestComposeMetrics(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
|
||||
t.Run("catch specific failure metrics", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/does-not-exist/compose.yaml", "build")
|
||||
expectedErr := "fixtures/does-not-exist/compose.yaml: no such file or directory"
|
||||
if runtime.GOOS == "windows" {
|
||||
expectedErr = "does-not-exist\\compose.yaml: The system cannot find the path specified"
|
||||
}
|
||||
res.Assert(t, icmd.Expected{ExitCode: 14, Err: expectedErr})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/wrong-composefile/compose.yaml", "up", "-d")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 15, Err: "services.simple Additional property wrongField is not allowed"})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "up")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 14, Err: "no configuration file provided: not found"})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "up", "-f", "fixtures/wrong-composefile/compose.yaml", "--menu=false")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 16, Err: "unknown shorthand flag: 'f' in -f"})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "up", "--file", "fixtures/wrong-composefile/compose.yaml", "--menu=false")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 16, Err: "unknown flag: --file"})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "donw", "--file", "fixtures/wrong-composefile/compose.yaml")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 16, Err: `unknown docker command: "compose donw"`})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "--file", "fixtures/wrong-composefile/build-error.yml", "build")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 17, Err: `line 17: unknown instruction: WRONG`})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "--file", "fixtures/wrong-composefile/build-error.yml", "up")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 17, Err: `line 17: unknown instruction: WRONG`})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "--file", "fixtures/wrong-composefile/unknown-image.yml", "pull")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 18, Err: `pull access denied for unknownimage, repository does not exist or may require 'docker login'`})
|
||||
res = c.RunDockerComposeCmdNoCheck(t, "--file", "fixtures/wrong-composefile/unknown-image.yml", "up")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 18, Err: `pull access denied for unknownimage, repository does not exist or may require 'docker login'`})
|
||||
})
|
||||
}
|
@ -82,7 +82,7 @@ func TestComposePull(t *testing.T) {
|
||||
|
||||
t.Run("Verify pull failure", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/compose-pull/unknown-image", "pull")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 18, Err: "pull access denied for does_not_exists"})
|
||||
res.Assert(t, icmd.Expected{ExitCode: 1, Err: "pull access denied for does_not_exists"})
|
||||
})
|
||||
|
||||
t.Run("Verify ignore pull failure", func(t *testing.T) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user