From 9ae6229068877bac1b4543075d23962d11bc6956 Mon Sep 17 00:00:00 2001 From: Marc Guasch Date: Tue, 7 Nov 2023 13:29:36 +0100 Subject: [PATCH 1/3] Add ignore_service_error flag. This will allow to selectively ignore or not an error in a test service container. --- docs/howto/system_testing.md | 1 + internal/compose/compose.go | 37 ++- internal/servicedeployer/compose.go | 16 ++ internal/servicedeployer/deployed_service.go | 3 + internal/servicedeployer/kubernetes.go | 4 + internal/testrunner/runners/system/runner.go | 10 + .../testrunner/runners/system/test_config.go | 5 + ...ocker_failing_test_service.expected_errors | 1 + .../_dev/build/build.yml | 3 + .../_dev/build/docs/README.md | 1 + .../docker_failing_test_service/changelog.yml | 6 + .../log/_dev/deploy/docker/docker-compose.yml | 8 + .../log/_dev/deploy/docker/logs/logs.log | 2 + .../log/_dev/test/system/test-fail-config.yml | 9 + .../log/agent/stream/stream.yml.hbs | 5 + .../elasticsearch/ingest_pipeline/default.yml | 6 + .../data_stream/log/fields/fields.yml | 230 ++++++++++++++++++ .../data_stream/log/manifest.yml | 14 ++ .../docs/README.md | 1 + .../docker_failing_test_service/manifest.yml | 22 ++ 20 files changed, 382 insertions(+), 2 deletions(-) create mode 100644 test/packages/false_positives/docker_failing_test_service.expected_errors create mode 100644 test/packages/false_positives/docker_failing_test_service/_dev/build/build.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/_dev/build/docs/README.md create mode 100644 test/packages/false_positives/docker_failing_test_service/changelog.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/docker-compose.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/logs/logs.log create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/test/system/test-fail-config.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/agent/stream/stream.yml.hbs create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/elasticsearch/ingest_pipeline/default.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/fields/fields.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/data_stream/log/manifest.yml create mode 100644 test/packages/false_positives/docker_failing_test_service/docs/README.md create mode 100644 test/packages/false_positives/docker_failing_test_service/manifest.yml diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index 8831f95da1..82c7ccaa3b 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -409,6 +409,7 @@ for system tests. | Option | Type | Required | Description | |---|---|---|---| | data_stream.vars | dictionary | | Data stream level variables to set (i.e. declared in `package_root/data_stream/$data_stream/manifest.yml`). If not specified the defaults from the manifest are used. | +| ignore_service_error | boolean | no | If `true`, it will ignore any failures in the deployed test services. Defaults to `true`. | | input | string | yes | Input type to test (e.g. logfile, httpjson, etc). Defaults to the input used by the first stream in the data stream manifest. | | numeric_keyword_fields | []string | | List of fields to ignore during validation that are mapped as `keyword` in Elasticsearch, but their JSON data type is a number. | | policy_template | string | | Name of policy template associated with the data stream and input. Required when multiple policy templates include the input being tested. | diff --git a/internal/compose/compose.go b/internal/compose/compose.go index 3087218f57..80a82b69f4 100644 --- a/internal/compose/compose.go +++ b/internal/compose/compose.go @@ -318,8 +318,7 @@ func (p *Project) Logs(opts CommandOptions) ([]byte, error) { func (p *Project) WaitForHealthy(opts CommandOptions) error { // Read container IDs args := p.baseArgs() - args = append(args, "ps") - args = append(args, "-q") + args = append(args, "ps", "-a", "-q") var b bytes.Buffer if err := p.runDockerComposeCmd(dockerComposeOptions{args: args, env: opts.Env, stdout: &b}); err != nil { @@ -387,6 +386,40 @@ func (p *Project) WaitForHealthy(opts CommandOptions) error { return nil } +// ServiceExitCode returns true if the specified service is exited with an error. +func (p *Project) ServiceExitCode(service string, opts CommandOptions) (bool, int, error) { + // Read container IDs + args := p.baseArgs() + args = append(args, "ps", "-a", "-q", service) + + var b bytes.Buffer + if err := p.runDockerComposeCmd(dockerComposeOptions{args: args, env: opts.Env, stdout: &b}); err != nil { + return false, -1, err + } + + containerIDs := strings.Fields(b.String()) + if len(containerIDs) != 1 { + return false, -1, fmt.Errorf("expected to find one service container named: %s, found: %d", service, len(containerIDs)) + } + containerID := containerIDs[0] + + containerDescriptions, err := docker.InspectContainers(containerID) + if err != nil { + return false, -1, err + } + if len(containerDescriptions) != 1 { + return false, -1, fmt.Errorf("expected to get one service status, found: %d", len(containerIDs)) + } + containerDescription := containerDescriptions[0] + + // Container exited with code > 0 + if containerDescription.State.Status == "exited" { + return true, containerDescription.State.ExitCode, nil + } + + return false, -1, nil +} + func (p *Project) baseArgs() []string { var args []string for _, path := range p.composeFilePaths { diff --git a/internal/servicedeployer/compose.go b/internal/servicedeployer/compose.go index 206b87f9c4..1b291552fa 100644 --- a/internal/servicedeployer/compose.go +++ b/internal/servicedeployer/compose.go @@ -155,6 +155,22 @@ func (s *dockerComposeDeployedService) Signal(signal string) error { return nil } +// ExitCode returns true if the service is exited and its exit code. +func (s *dockerComposeDeployedService) ExitCode(service string) (bool, int, error) { + p, err := compose.NewProject(s.project, s.ymlPaths...) + if err != nil { + return false, -1, fmt.Errorf("could not create Docker Compose project for service: %w", err) + } + + opts := compose.CommandOptions{ + Env: append( + s.env, + s.variant.Env...), + } + + return p.ServiceExitCode(service, opts) +} + // TearDown tears down the service. func (s *dockerComposeDeployedService) TearDown() error { logger.Debugf("tearing down service using Docker Compose runner") diff --git a/internal/servicedeployer/deployed_service.go b/internal/servicedeployer/deployed_service.go index ebd1a87f9e..cb7bc2328a 100644 --- a/internal/servicedeployer/deployed_service.go +++ b/internal/servicedeployer/deployed_service.go @@ -17,4 +17,7 @@ type DeployedService interface { // SetContext sets the current context for the service. SetContext(str ServiceContext) error + + // ExitCode returns true if the service is exited and its exit code. + ExitCode(service string) (bool, int, error) } diff --git a/internal/servicedeployer/kubernetes.go b/internal/servicedeployer/kubernetes.go index b76c56b2b4..a61170b294 100644 --- a/internal/servicedeployer/kubernetes.go +++ b/internal/servicedeployer/kubernetes.go @@ -60,6 +60,10 @@ func (s kubernetesDeployedService) Signal(_ string) error { return errors.New("signal is not supported") } +func (s kubernetesDeployedService) ExitCode(_ string) (bool, int, error) { + return false, -1, errors.New("exit code is not supported") +} + func (s kubernetesDeployedService) Context() ServiceContext { return s.ctxt } diff --git a/internal/testrunner/runners/system/runner.go b/internal/testrunner/runners/system/runner.go index 1431f48c63..ccdac04fb3 100644 --- a/internal/testrunner/runners/system/runner.go +++ b/internal/testrunner/runners/system/runner.go @@ -753,6 +753,16 @@ func (r *runner) runTest(config *testConfig, ctxt servicedeployer.ServiceContext return result.WithError(err) } + if config.Service != "" && !config.MustIgnoreServiceError() { + exited, code, err := service.ExitCode(config.Service) + if err != nil { + return result.WithError(err) + } + if exited && code > 0 { + result.FailureMsg = fmt.Sprintf("the test service %s unexpectedly exited with code %d", config.Service, code) + } + } + return result.WithSuccess() } diff --git a/internal/testrunner/runners/system/test_config.go b/internal/testrunner/runners/system/test_config.go index 6a55f9d27d..6a04ab32e1 100644 --- a/internal/testrunner/runners/system/test_config.go +++ b/internal/testrunner/runners/system/test_config.go @@ -32,6 +32,7 @@ type testConfig struct { PolicyTemplate string `config:"policy_template"` // Policy template associated with input. Required when multiple policy templates include the input being tested. Service string `config:"service"` ServiceNotifySignal string `config:"service_notify_signal"` // Signal to send when the agent policy is applied. + IgnoreServiceError *bool `config:"ignore_service_error"` WaitForDataTimeout time.Duration `config:"wait_for_data_timeout"` Vars common.MapStr `config:"vars"` @@ -69,6 +70,10 @@ func (t testConfig) Name() string { return sb.String() } +func (t testConfig) MustIgnoreServiceError() bool { + return t.IgnoreServiceError == nil || *t.IgnoreServiceError +} + func newConfig(configFilePath string, ctxt servicedeployer.ServiceContext, serviceVariantName string) (*testConfig, error) { data, err := os.ReadFile(configFilePath) if err != nil && errors.Is(err, os.ErrNotExist) { diff --git a/test/packages/false_positives/docker_failing_test_service.expected_errors b/test/packages/false_positives/docker_failing_test_service.expected_errors new file mode 100644 index 0000000000..793f8c85f0 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service.expected_errors @@ -0,0 +1 @@ + * the test service failing unexpectedly exited with code 1 diff --git a/test/packages/false_positives/docker_failing_test_service/_dev/build/build.yml b/test/packages/false_positives/docker_failing_test_service/_dev/build/build.yml new file mode 100644 index 0000000000..c8eeec8cac --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/_dev/build/build.yml @@ -0,0 +1,3 @@ +dependencies: + ecs: + reference: git@v8.9.0 diff --git a/test/packages/false_positives/docker_failing_test_service/_dev/build/docs/README.md b/test/packages/false_positives/docker_failing_test_service/_dev/build/docs/README.md new file mode 100644 index 0000000000..9bf8658535 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/_dev/build/docs/README.md @@ -0,0 +1 @@ +# Test integration \ No newline at end of file diff --git a/test/packages/false_positives/docker_failing_test_service/changelog.yml b/test/packages/false_positives/docker_failing_test_service/changelog.yml new file mode 100644 index 0000000000..58db18ef3e --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "999.999.999" + changes: + - description: Test + type: enhancement + link: https://github.com/elastic/integrations/pull/99999 diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/docker-compose.yml b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/docker-compose.yml new file mode 100644 index 0000000000..5b7f52d0c3 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/docker-compose.yml @@ -0,0 +1,8 @@ +version: '2.3' +services: + failing: + image: alpine + volumes: + - ./logs:/logs:ro + - ${SERVICE_LOGS_DIR}:/var/log + command: /bin/sh -c "echo \"Sleep 10s...\"; sleep 10; echo \"Copying files...\"; cp /logs/* /var/log/; echo \"Done.\"; sleep 5; exit 1" diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/logs/logs.log b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/logs/logs.log new file mode 100644 index 0000000000..3bd1f0e297 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/deploy/docker/logs/logs.log @@ -0,0 +1,2 @@ +foo +bar diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/test/system/test-fail-config.yml b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/test/system/test-fail-config.yml new file mode 100644 index 0000000000..dcfe5eb9cf --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/_dev/test/system/test-fail-config.yml @@ -0,0 +1,9 @@ +input: logfile +service: failing +ignore_service_error: false +data_stream: + vars: + paths: + - "{{SERVICE_LOGS_DIR}}/*.log" +assert: + hit_count: 2 diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/agent/stream/stream.yml.hbs b/test/packages/false_positives/docker_failing_test_service/data_stream/log/agent/stream/stream.yml.hbs new file mode 100644 index 0000000000..e4e997e3bb --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/agent/stream/stream.yml.hbs @@ -0,0 +1,5 @@ +paths: +{{#each paths as |path i|}} + - {{path}} +{{/each}} +exclude_files: [".gz$"] diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/elasticsearch/ingest_pipeline/default.yml b/test/packages/false_positives/docker_failing_test_service/data_stream/log/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 0000000000..984fc41fc3 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,6 @@ +--- +description: "Pipeline for Cisco ASA logs" +processors: + - set: + field: ecs.version + value: '8.9.0' diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/fields/fields.yml b/test/packages/false_positives/docker_failing_test_service/data_stream/log/fields/fields.yml new file mode 100644 index 0000000000..97a48492f6 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/fields/fields.yml @@ -0,0 +1,230 @@ +- name: ecs.version + type: keyword +- name: log.file.path + type: keyword +- name: message + type: keyword +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: event.module + type: constant_keyword + description: Event module +- name: event.dataset + type: constant_keyword + description: Event dataset +- name: "@timestamp" + type: date +- name: cloud + title: Cloud + group: 2 + description: Fields related to the cloud or infrastructure the events are coming from. + footnote: 'Examples: If Metricbeat is running on an EC2 host and fetches data from its host, the cloud info contains the data about this machine. If Metricbeat runs on a remote machine outside the cloud and fetches data from a service running in the cloud, the field contains cloud data from the machine the service is running on.' + type: group + fields: + - name: account.id + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud account or organization id used to identify different entities in a multi-tenant environment. + + Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.' + example: 666777888999 + - name: availability_zone + level: extended + type: keyword + ignore_above: 1024 + description: Availability zone in which this host is running. + example: us-east-1c + - name: instance.id + level: extended + type: keyword + ignore_above: 1024 + description: Instance ID of the host machine. + example: i-1234567890abcdef0 + - name: instance.name + level: extended + type: keyword + ignore_above: 1024 + description: Instance name of the host machine. + - name: machine.type + level: extended + type: keyword + ignore_above: 1024 + description: Machine type of the host machine. + example: t2.medium + - name: provider + level: extended + type: keyword + ignore_above: 1024 + description: Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. + example: aws + - name: region + level: extended + type: keyword + ignore_above: 1024 + description: Region in which this host is running. + example: us-east-1 + - name: project.id + type: keyword + description: Name of the project in Google Cloud. + - name: image.id + type: keyword + description: Image ID for the cloud instance. +- name: container + title: Container + group: 2 + description: 'Container fields are used for meta information about the specific container that is the source of information. + + These fields help correlate data based containers from any runtime.' + type: group + fields: + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique container id. + - name: image.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the image the container was built on. + - name: labels + level: extended + type: object + object_type: keyword + description: Image labels. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Container name. +- name: host + title: Host + group: 2 + description: 'A host is defined as a general computing instance. + + ECS host.* fields should be populated with details about the host on which the event happened, or from which the measurement was taken. Host types include hardware, virtual machines, Docker containers, and Kubernetes nodes.' + type: group + fields: + - name: architecture + level: core + type: keyword + ignore_above: 1024 + description: Operating system architecture. + example: x86_64 + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the domain of which the host is a member. + + For example, on Windows this could be the host''s Active Directory domain or NetBIOS domain name. For Linux this could be the domain of the host''s LDAP provider.' + example: CONTOSO + default_field: false + - name: hostname + level: core + type: keyword + ignore_above: 1024 + description: 'Hostname of the host. + + It normally contains what the `hostname` command returns on the host machine.' + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique host id. + + As hostname is not always unique, use values that are meaningful in your environment. + + Example: The current usage of `beat.name`.' + - name: ip + level: core + type: ip + description: Host ip addresses. + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: Host mac addresses. + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the host. + + It can contain what `hostname` returns on Unix systems, the fully qualified domain name, or a name specified by the user. The sender decides which value to use.' + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'Type of host. + + For Cloud providers this can be the machine type like `t2.medium`. If vm, this could be the container, for example, or other information meaningful in your environment.' + - name: containerized + type: boolean + description: > + If the host is a container. + + - name: os.build + type: keyword + example: "18D109" + description: > + OS build information. + + - name: os.codename + type: keyword + example: "stretch" + description: > + OS codename, if any. + +- name: input.type + type: keyword + description: Input type. +- name: log.offset + type: long + description: Offset of the entry in the log file. +- name: log.source.address + type: keyword + description: Source address from which the log event was read / sent from. diff --git a/test/packages/false_positives/docker_failing_test_service/data_stream/log/manifest.yml b/test/packages/false_positives/docker_failing_test_service/data_stream/log/manifest.yml new file mode 100644 index 0000000000..a47baee0f8 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/data_stream/log/manifest.yml @@ -0,0 +1,14 @@ +title: Test +type: logs +streams: + - input: logfile + enabled: false + title: Test + description: Test + vars: + - name: paths + type: text + title: Paths + multi: true + required: true + show_user: true diff --git a/test/packages/false_positives/docker_failing_test_service/docs/README.md b/test/packages/false_positives/docker_failing_test_service/docs/README.md new file mode 100644 index 0000000000..9bf8658535 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/docs/README.md @@ -0,0 +1 @@ +# Test integration \ No newline at end of file diff --git a/test/packages/false_positives/docker_failing_test_service/manifest.yml b/test/packages/false_positives/docker_failing_test_service/manifest.yml new file mode 100644 index 0000000000..e55dffec68 --- /dev/null +++ b/test/packages/false_positives/docker_failing_test_service/manifest.yml @@ -0,0 +1,22 @@ +format_version: 3.0.0 +name: docker_failing_test_service +title: Test +version: "999.999.999" +description: Test +type: integration +categories: + - network +conditions: + kibana: + version: "^8.7.1" +policy_templates: + - name: test + title: Test + description: Test + inputs: + - type: logfile + title: Test + description: Test +owner: + github: elastic/security-external-integrations + type: elastic From d79306a9ac1739cc70f11272f269b94b25e7360d Mon Sep 17 00:00:00 2001 From: Marc Guasch Date: Tue, 7 Nov 2023 16:44:04 +0100 Subject: [PATCH 2/3] Make it default to false --- docs/howto/system_testing.md | 2 +- internal/testrunner/runners/system/runner.go | 2 +- internal/testrunner/runners/system/test_config.go | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index 82c7ccaa3b..4f982b1b68 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -409,7 +409,7 @@ for system tests. | Option | Type | Required | Description | |---|---|---|---| | data_stream.vars | dictionary | | Data stream level variables to set (i.e. declared in `package_root/data_stream/$data_stream/manifest.yml`). If not specified the defaults from the manifest are used. | -| ignore_service_error | boolean | no | If `true`, it will ignore any failures in the deployed test services. Defaults to `true`. | +| ignore_service_error | boolean | no | If `true`, it will ignore any failures in the deployed test services. Defaults to `false`. | | input | string | yes | Input type to test (e.g. logfile, httpjson, etc). Defaults to the input used by the first stream in the data stream manifest. | | numeric_keyword_fields | []string | | List of fields to ignore during validation that are mapped as `keyword` in Elasticsearch, but their JSON data type is a number. | | policy_template | string | | Name of policy template associated with the data stream and input. Required when multiple policy templates include the input being tested. | diff --git a/internal/testrunner/runners/system/runner.go b/internal/testrunner/runners/system/runner.go index ccdac04fb3..a22ce42899 100644 --- a/internal/testrunner/runners/system/runner.go +++ b/internal/testrunner/runners/system/runner.go @@ -753,7 +753,7 @@ func (r *runner) runTest(config *testConfig, ctxt servicedeployer.ServiceContext return result.WithError(err) } - if config.Service != "" && !config.MustIgnoreServiceError() { + if config.Service != "" && !config.IgnoreServiceError { exited, code, err := service.ExitCode(config.Service) if err != nil { return result.WithError(err) diff --git a/internal/testrunner/runners/system/test_config.go b/internal/testrunner/runners/system/test_config.go index 6a04ab32e1..5a88520d0a 100644 --- a/internal/testrunner/runners/system/test_config.go +++ b/internal/testrunner/runners/system/test_config.go @@ -32,7 +32,7 @@ type testConfig struct { PolicyTemplate string `config:"policy_template"` // Policy template associated with input. Required when multiple policy templates include the input being tested. Service string `config:"service"` ServiceNotifySignal string `config:"service_notify_signal"` // Signal to send when the agent policy is applied. - IgnoreServiceError *bool `config:"ignore_service_error"` + IgnoreServiceError bool `config:"ignore_service_error"` WaitForDataTimeout time.Duration `config:"wait_for_data_timeout"` Vars common.MapStr `config:"vars"` @@ -70,10 +70,6 @@ func (t testConfig) Name() string { return sb.String() } -func (t testConfig) MustIgnoreServiceError() bool { - return t.IgnoreServiceError == nil || *t.IgnoreServiceError -} - func newConfig(configFilePath string, ctxt servicedeployer.ServiceContext, serviceVariantName string) (*testConfig, error) { data, err := os.ReadFile(configFilePath) if err != nil && errors.Is(err, os.ErrNotExist) { From 6a8b3ecb22518fda7c9680387364ce3d6deb0a0a Mon Sep 17 00:00:00 2001 From: Marc Guasch Date: Wed, 8 Nov 2023 12:20:18 +0100 Subject: [PATCH 3/3] Check for not supported error --- internal/servicedeployer/deployed_service.go | 4 ++++ internal/servicedeployer/kubernetes.go | 5 ++--- internal/testrunner/runners/system/runner.go | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/servicedeployer/deployed_service.go b/internal/servicedeployer/deployed_service.go index cb7bc2328a..dc6822022c 100644 --- a/internal/servicedeployer/deployed_service.go +++ b/internal/servicedeployer/deployed_service.go @@ -4,6 +4,10 @@ package servicedeployer +import "errors" + +var ErrNotSupported error = errors.New("not supported") + // DeployedService defines the interface for interacting with a service that has been deployed. type DeployedService interface { // TearDown implements the logic for tearing down a service. diff --git a/internal/servicedeployer/kubernetes.go b/internal/servicedeployer/kubernetes.go index a61170b294..c3dffa607c 100644 --- a/internal/servicedeployer/kubernetes.go +++ b/internal/servicedeployer/kubernetes.go @@ -8,7 +8,6 @@ import ( "bytes" _ "embed" "encoding/base64" - "errors" "fmt" "os" "path/filepath" @@ -57,11 +56,11 @@ func (s kubernetesDeployedService) TearDown() error { } func (s kubernetesDeployedService) Signal(_ string) error { - return errors.New("signal is not supported") + return ErrNotSupported } func (s kubernetesDeployedService) ExitCode(_ string) (bool, int, error) { - return false, -1, errors.New("exit code is not supported") + return false, -1, ErrNotSupported } func (s kubernetesDeployedService) Context() ServiceContext { diff --git a/internal/testrunner/runners/system/runner.go b/internal/testrunner/runners/system/runner.go index a22ce42899..d5a5696724 100644 --- a/internal/testrunner/runners/system/runner.go +++ b/internal/testrunner/runners/system/runner.go @@ -755,7 +755,7 @@ func (r *runner) runTest(config *testConfig, ctxt servicedeployer.ServiceContext if config.Service != "" && !config.IgnoreServiceError { exited, code, err := service.ExitCode(config.Service) - if err != nil { + if err != nil && !errors.Is(err, servicedeployer.ErrNotSupported) { return result.WithError(err) } if exited && code > 0 {