diff --git a/code/go/internal/validator/spec.go b/code/go/internal/validator/spec.go index f47754788..0488285ed 100644 --- a/code/go/internal/validator/spec.go +++ b/code/go/internal/validator/spec.go @@ -7,6 +7,7 @@ package validator import ( "io/fs" "log" + "strings" "github.com/Masterminds/semver/v3" "github.com/pkg/errors" @@ -64,7 +65,45 @@ func (s Spec) ValidatePackage(pkg Package) ve.ValidationErrors { // Semantic validations errs = append(errs, s.rules(rootSpec).validate(&pkg)...) - return errs + return processErrors(errs) +} + +func substringInSlice(str string, list []string) bool { + for _, substr := range list { + if strings.Contains(str, substr) { + return true + } + } + return false +} + +func processErrors(errs ve.ValidationErrors) ve.ValidationErrors { + // Rename unclear error messages and filter out redundant errors + var processedErrs ve.ValidationErrors + msgTransforms := []struct { + original string + new string + }{ + {"Must not validate the schema (not)", "Must not be present"}, + } + redundant := []string{ + "Must validate \"then\" as \"if\" was valid", + "Must validate \"else\" as \"if\" was not valid", + } + for _, e := range errs { + for _, msg := range msgTransforms { + if strings.Contains(e.Error(), msg.original) { + processedErrs = append(processedErrs, errors.New(strings.Replace(e.Error(), msg.original, msg.new, 1))) + continue + } + if substringInSlice(e.Error(), redundant) { + continue + } + processedErrs = append(processedErrs, e) + } + } + + return processedErrs } func (s Spec) rules(rootSpec spectypes.ItemSpec) validationRules { diff --git a/code/go/pkg/validator/validator_test.go b/code/go/pkg/validator/validator_test.go index 6e3273395..b354e96c5 100644 --- a/code/go/pkg/validator/validator_test.go +++ b/code/go/pkg/validator/validator_test.go @@ -99,7 +99,7 @@ func TestValidateFile(t *testing.T) { "deploy_custom_agent_invalid_property": { "_dev/deploy/agent/custom-agent.yml", []string{ - "field services.docker-custom-agent: Must not validate the schema (not)", + "field services.docker-custom-agent: Must not be present", }, }, "invalid_field_for_version": { @@ -120,6 +120,14 @@ func TestValidateFile(t *testing.T) { fmt.Sprintf("field ilm_policy: ILM policy \"logs-bad_custom_ilm_policy.test-notexists\" not found in package, expected definition in \"%sbad_custom_ilm_policy/data_stream/test/elasticsearch/ilm/notexists.json\"", osTestBasePath), }, }, + "bad_select": { + "data_stream/foo_stream/manifest.yml", + []string{ + "field streams.0.vars.1: options is required", + "field streams.0.vars.2.options: Invalid type. Expected: array, given: null", + "field streams.0.vars.3: Must not be present", + }, + }, } for pkgName, test := range tests { diff --git a/spec/changelog.yml b/spec/changelog.yml index 46cd3d873..f4be43a75 100644 --- a/spec/changelog.yml +++ b/spec/changelog.yml @@ -10,6 +10,9 @@ - description: Add date_format to field of type date type: enhancement link: https://github.com/elastic/package-spec/pull/481 + - description: Add select as a new field type + type: enhancement + link: https://github.com/elastic/package-spec/pull/486 - version: 2.5.1 changes: - description: Add category for vulnerability_management diff --git a/spec/integration/data_stream/manifest.spec.yml b/spec/integration/data_stream/manifest.spec.yml index fbbbb5bb6..3b3ac2c04 100644 --- a/spec/integration/data_stream/manifest.spec.yml +++ b/spec/integration/data_stream/manifest.spec.yml @@ -52,6 +52,7 @@ spec: - email - integer - password + - select - text - textarea - time_zone @@ -75,6 +76,7 @@ spec: default: false examples: - true + options: true # This allows options to be required when type is select. required: description: Is variable required? type: boolean @@ -102,6 +104,39 @@ spec: default: description: Default value(s) for variable $ref: "#/definitions/input_variable_value" + if: + properties: + type: + const: select + then: + required: + - options + properties: + options: + description: List of options for select type + type: array + items: + type: object + additionalProperties: false + properties: + value: + type: string + examples: + - node + - cluster + text: + type: string + examples: + - node + - cluster + required: + - value + - text + min_items: 1 + else: + not: + required: + - options required: - name - type @@ -273,3 +308,8 @@ spec: type: boolean required: - title +versions: + - before: 2.6.0 + patch: + - op: remove + path: /definitions/vars/items/properties/type/enum/4 diff --git a/test/packages/bad_select/LICENSE.txt b/test/packages/bad_select/LICENSE.txt new file mode 100644 index 000000000..809108b85 --- /dev/null +++ b/test/packages/bad_select/LICENSE.txt @@ -0,0 +1,93 @@ +Elastic License 2.0 + +URL: https://www.elastic.co/licensing/elastic-license + +## Acceptance + +By using the software, you agree to all of the terms and conditions below. + +## Copyright License + +The licensor grants you a non-exclusive, royalty-free, worldwide, +non-sublicensable, non-transferable license to use, copy, distribute, make +available, and prepare derivative works of the software, in each case subject to +the limitations and conditions below. + +## Limitations + +You may not provide the software to third parties as a hosted or managed +service, where the service provides users with access to any substantial set of +the features or functionality of the software. + +You may not move, change, disable, or circumvent the license key functionality +in the software, and you may not remove or obscure any functionality in the +software that is protected by the license key. + +You may not alter, remove, or obscure any licensing, copyright, or other notices +of the licensor in the software. Any use of the licensor’s trademarks is subject +to applicable law. + +## Patents + +The licensor grants you a license, under any patent claims the licensor can +license, or becomes able to license, to make, have made, use, sell, offer for +sale, import and have imported the software, in each case subject to the +limitations and conditions in this license. This license does not cover any +patent claims that you cause to be infringed by modifications or additions to +the software. If you or your company make any written claim that the software +infringes or contributes to infringement of any patent, your patent license for +the software granted under these terms ends immediately. If your company makes +such a claim, your patent license ends immediately for work on behalf of your +company. + +## Notices + +You must ensure that anyone who gets a copy of any part of the software from you +also gets a copy of these terms. + +If you modify the software, you must include in any modified copies of the +software prominent notices stating that you have modified the software. + +## No Other Rights + +These terms do not imply any licenses other than those expressly granted in +these terms. + +## Termination + +If you use the software in violation of these terms, such use is not licensed, +and your licenses will automatically terminate. If the licensor provides you +with a notice of your violation, and you cease all violation of this license no +later than 30 days after you receive that notice, your licenses will be +reinstated retroactively. However, if you violate these terms after such +reinstatement, any additional violation of these terms will cause your licenses +to terminate automatically and permanently. + +## No Liability + +*As far as the law allows, the software comes as is, without any warranty or +condition, and the licensor will not be liable to you for any damages arising +out of these terms or the use or nature of the software, under any kind of +legal claim.* + +## Definitions + +The **licensor** is the entity offering these terms, and the **software** is the +software the licensor makes available under these terms, including any portion +of it. + +**you** refers to the individual or entity agreeing to these terms. + +**your company** is any legal entity, sole proprietorship, or other kind of +organization that you work for, plus all organizations that have control over, +are under the control of, or are under common control with that +organization. **control** means ownership of substantially all the assets of an +entity, or the power to direct its management and policies by vote, contract, or +otherwise. Control can be direct or indirect. + +**your licenses** are all the licenses granted to you for the software under +these terms. + +**use** means anything you do with the software requiring one of your licenses. + +**trademark** means trademarks, service marks, and similar rights. diff --git a/test/packages/bad_select/changelog.yml b/test/packages/bad_select/changelog.yml new file mode 100644 index 000000000..bb0320a52 --- /dev/null +++ b/test/packages/bad_select/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "0.0.1" + changes: + - description: Initial draft of the package + type: enhancement + link: https://github.com/elastic/integrations/pull/1 # FIXME Replace with the real PR link diff --git a/test/packages/bad_select/data_stream/foo_stream/agent/stream/stream.yml.hbs b/test/packages/bad_select/data_stream/foo_stream/agent/stream/stream.yml.hbs new file mode 100644 index 000000000..3e1cf2259 --- /dev/null +++ b/test/packages/bad_select/data_stream/foo_stream/agent/stream/stream.yml.hbs @@ -0,0 +1,6 @@ +metricsets: ["sample_metricset"] +hosts: +{{#each hosts}} + - {{this}} +{{/each}} +period: {{period}} diff --git a/test/packages/bad_select/data_stream/foo_stream/fields/base-fields.yml b/test/packages/bad_select/data_stream/foo_stream/fields/base-fields.yml new file mode 100644 index 000000000..7c798f453 --- /dev/null +++ b/test/packages/bad_select/data_stream/foo_stream/fields/base-fields.yml @@ -0,0 +1,12 @@ +- 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: '@timestamp' + type: date + description: Event timestamp. diff --git a/test/packages/bad_select/data_stream/foo_stream/manifest.yml b/test/packages/bad_select/data_stream/foo_stream/manifest.yml new file mode 100644 index 000000000..c736cbd2b --- /dev/null +++ b/test/packages/bad_select/data_stream/foo_stream/manifest.yml @@ -0,0 +1,29 @@ +title: "Foo Stream" +type: metrics +streams: + - input: sample/metrics + title: Sample metrics + description: Collect sample metrics + vars: + - name: period + type: text + title: Period + default: 10s + - name: first_select + type: select + title: First Select + - name: second_select + type: select + title: Second Select + options: [] + - name: my_text + type: text + title: My Text + multi: false + required: false + show_user: false + options: + - value: foo + text: Foo + - value: bar + text: Bar diff --git a/test/packages/bad_select/docs/README.md b/test/packages/bad_select/docs/README.md new file mode 100644 index 000000000..be894e5c3 --- /dev/null +++ b/test/packages/bad_select/docs/README.md @@ -0,0 +1,84 @@ + + + +# Bad Select + + + +## Data streams + + + + + + + + + + + +## Requirements + +You need Elasticsearch for storing and searching your data and Kibana for visualizing and managing it. +You can use our hosted Elasticsearch Service on Elastic Cloud, which is recommended, or self-manage the Elastic Stack on your own hardware. + + + +## Setup + + + +For step-by-step instructions on how to set up an integration, see the +[Getting started](https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-observability.html) guide. + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/packages/bad_select/img/sample-logo.svg b/test/packages/bad_select/img/sample-logo.svg new file mode 100644 index 000000000..6268dd88f --- /dev/null +++ b/test/packages/bad_select/img/sample-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/packages/bad_select/img/sample-screenshot.png b/test/packages/bad_select/img/sample-screenshot.png new file mode 100644 index 000000000..d7a56a3ec Binary files /dev/null and b/test/packages/bad_select/img/sample-screenshot.png differ diff --git a/test/packages/bad_select/manifest.yml b/test/packages/bad_select/manifest.yml new file mode 100644 index 000000000..0d9aa7988 --- /dev/null +++ b/test/packages/bad_select/manifest.yml @@ -0,0 +1,33 @@ +format_version: 2.6.0 +name: bad_select +title: "Bad Select" +version: 0.0.1 +source: + license: "Elastic-2.0" +description: "Invalid package as select options are invalid" +type: integration +categories: + - custom +conditions: + kibana.version: "^8.6.1" + elastic.subscription: "basic" +screenshots: + - src: /img/sample-screenshot.png + title: Sample screenshot + size: 600x600 + type: image/png +icons: + - src: /img/sample-logo.svg + title: Sample logo + size: 32x32 + type: image/svg+xml +policy_templates: + - name: sample + title: Sample logs + description: Collect sample logs + inputs: + - type: logfile + title: Collect sample logs from instances + description: Collecting sample logs +owner: + github: elastic/ecosystem diff --git a/test/packages/good_input/manifest.yml b/test/packages/good_input/manifest.yml index 5ae23ee63..3dbd8a53c 100644 --- a/test/packages/good_input/manifest.yml +++ b/test/packages/good_input/manifest.yml @@ -1,4 +1,4 @@ -format_version: 2.3.0 +format_version: 2.6.0 name: good_input title: good_input description: >- @@ -58,6 +58,18 @@ policy_templates: required: true show_user: false default: "variables" + - name: sql_response_caching + type: select + title: Response caching + description: "Optional response caching time" + multi: false + required: true + show_user: false + options: + - value: "0" + text: None + - value: "1" + text: "1 day" icons: - src: "/img/sample-logo.svg" type: "image/svg+xml" diff --git a/test/packages/good_v2/data_stream/foo/manifest.yml b/test/packages/good_v2/data_stream/foo/manifest.yml index 7b2aa77a2..4dfc8f20c 100644 --- a/test/packages/good_v2/data_stream/foo/manifest.yml +++ b/test/packages/good_v2/data_stream/foo/manifest.yml @@ -25,6 +25,17 @@ streams: required: true show_user: false default: /server-status + - name: my_select + type: select + title: My Select + multi: false + required: false + show_user: false + options: + - value: foo + text: Foo + - value: bar + text: Bar title: Nginx access logs description: Collect Nginx access logs dataset_is_prefix: true diff --git a/test/packages/good_v2/manifest.yml b/test/packages/good_v2/manifest.yml index e398eafea..4ff639eee 100644 --- a/test/packages/good_v2/manifest.yml +++ b/test/packages/good_v2/manifest.yml @@ -1,4 +1,4 @@ -format_version: 2.3.0 +format_version: 2.6.0 name: good_v2 title: Good package description: This package is good for format version 2