diff --git a/code/go/internal/validator/semantic/validate_input_policy_template_template_path.go b/code/go/internal/validator/semantic/validate_input_policy_template_template_path.go new file mode 100644 index 000000000..d85b27e51 --- /dev/null +++ b/code/go/internal/validator/semantic/validate_input_policy_template_template_path.go @@ -0,0 +1,98 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package semantic + +import ( + "errors" + "fmt" + "io/fs" + "os" + "path" + + "gopkg.in/yaml.v3" + + "github.com/elastic/package-spec/v3/code/go/internal/fspath" + "github.com/elastic/package-spec/v3/code/go/pkg/specerrors" +) + +const ( + inputPackageType string = "input" +) + +var ( + errRequiredTemplatePath = errors.New("template_path is required for input type packages") + errFailedToReadManifest = errors.New("failed to read manifest") + errFailedToParseManifest = errors.New("failed to parse manifest") + errTemplateNotFound = errors.New("template file not found") + errInvalidPackageType = errors.New("invalid package type") +) + +type inputPolicyTemplate struct { + Name string `yaml:"name"` + TemplatePath string `yaml:"template_path"` // input type packages require this field +} + +type inputPackageManifest struct { // package manifest + Type string `yaml:"type"` + PolicyTemplates []inputPolicyTemplate `yaml:"policy_templates"` +} + +// ValidateInputPackagesPolicyTemplates validates the policy template entries of an input package +func ValidateInputPackagesPolicyTemplates(fsys fspath.FS) specerrors.ValidationErrors { + var errs specerrors.ValidationErrors + + manifestPath := "manifest.yml" + data, err := fs.ReadFile(fsys, manifestPath) + if err != nil { + return specerrors.ValidationErrors{ + specerrors.NewStructuredErrorf("file \"%s\" is invalid: %ww", fsys.Path(manifestPath), errFailedToReadManifest)} + } + + var manifest inputPackageManifest + err = yaml.Unmarshal(data, &manifest) + if err != nil { + return specerrors.ValidationErrors{ + specerrors.NewStructuredErrorf("file \"%s\" is invalid: %w", fsys.Path(manifestPath), errFailedToParseManifest)} + } + + if manifest.Type != inputPackageType { + return specerrors.ValidationErrors{ + specerrors.NewStructuredErrorf("file \"%s\" is invalid: expected package type \"%s\", got \"%s\": %w", + fsys.Path(manifestPath), inputPackageType, manifest.Type, errInvalidPackageType)} + } + + for _, policyTemplate := range manifest.PolicyTemplates { + err := validateInputPackagePolicyTemplate(fsys, policyTemplate) + if err != nil { + errs = append(errs, specerrors.NewStructuredErrorf( + "file \"%s\" is invalid: policy template \"%s\" references template_path \"%s\": %w", + fsys.Path(manifestPath), policyTemplate.Name, policyTemplate.TemplatePath, err)) + } + } + + return errs +} + +// validateInputPackagePolicyTemplate validates the template_path at the policy template level for input type packages +// if the template_path is empty, it returns an error as this field is required for input type packages +func validateInputPackagePolicyTemplate(fsys fspath.FS, policyTemplate inputPolicyTemplate) error { + if policyTemplate.TemplatePath == "" { + return errRequiredTemplatePath + } + return validateAgentInputTemplatePath(fsys, policyTemplate.TemplatePath) +} + +func validateAgentInputTemplatePath(fsys fspath.FS, tmplPath string) error { + templatePath := path.Join("agent", "input", tmplPath) + _, err := fs.Stat(fsys, templatePath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return errTemplateNotFound + } + return fmt.Errorf("failed to stat template file %s: %w", fsys.Path(templatePath), err) + } + + return nil +} diff --git a/code/go/internal/validator/semantic/validate_input_policy_template_template_path_test.go b/code/go/internal/validator/semantic/validate_input_policy_template_template_path_test.go new file mode 100644 index 000000000..538ff2bec --- /dev/null +++ b/code/go/internal/validator/semantic/validate_input_policy_template_template_path_test.go @@ -0,0 +1,97 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package semantic + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/package-spec/v3/code/go/internal/fspath" +) + +func TestValidateInputPackagesPolicyTemplates(t *testing.T) { + + t.Run("policy_templates_have_template_path", func(t *testing.T) { + d := t.TempDir() + + err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` +type: input +policy_templates: + - name: udp + template_path: udp.yml.hbs +`), 0o644) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(d, "agent", "input", "udp.yml.hbs"), []byte("# UDP template"), 0o644) + require.NoError(t, err) + + errs := ValidateInputPackagesPolicyTemplates(fspath.DirFS(d)) + require.Empty(t, errs, "expected no validation errors") + + }) + + t.Run("policy_templates_empty_template_path", func(t *testing.T) { + d := t.TempDir() + + err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` +type: input +policy_templates: + - name: udp +`), 0o644) + require.NoError(t, err) + + errs := ValidateInputPackagesPolicyTemplates(fspath.DirFS(d)) + require.NotEmpty(t, errs, "expected no validation errors") + + assert.Len(t, errs, 1) + assert.ErrorIs(t, errs[0], errRequiredTemplatePath) + }) + + t.Run("policy_templates_missing_template_path", func(t *testing.T) { + d := t.TempDir() + + err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` +type: input +policy_templates: + - name: udp + template_path: missing.yml.hbs +`), 0o644) + require.NoError(t, err) + + errs := ValidateInputPackagesPolicyTemplates(fspath.DirFS(d)) + require.NotEmpty(t, errs, "expected validation errors") + assert.Len(t, errs, 1) + assert.ErrorIs(t, errs[0], errTemplateNotFound) + }) + + t.Run("not_input_package_type", func(t *testing.T) { + d := t.TempDir() + + err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` +type: integration +policy_templates: + - name: udp + template_path: missing.yml.hbs +`), 0o644) + require.NoError(t, err) + + errs := ValidateInputPackagesPolicyTemplates(fspath.DirFS(d)) + require.NotEmpty(t, errs, "expected validation errors") + assert.Len(t, errs, 1) + assert.ErrorIs(t, errs[0], errInvalidPackageType) + }) + +} diff --git a/code/go/internal/validator/spec.go b/code/go/internal/validator/spec.go index 0db1c315d..d6dd2ca90 100644 --- a/code/go/internal/validator/spec.go +++ b/code/go/internal/validator/spec.go @@ -217,6 +217,7 @@ func (s Spec) rules(pkgType string, rootSpec spectypes.ItemSpec) validationRules {fn: semantic.ValidateDocsStructure}, {fn: semantic.ValidateDeploymentModes, types: []string{"integration"}}, {fn: semantic.ValidateDurationVariables, since: semver.MustParse("3.5.0")}, + {fn: semantic.ValidateInputPackagesPolicyTemplates, types: []string{"input"}}, } var validationRules validationRules diff --git a/code/go/pkg/validator/validator_test.go b/code/go/pkg/validator/validator_test.go index 90ff17ece..f56b802e5 100644 --- a/code/go/pkg/validator/validator_test.go +++ b/code/go/pkg/validator/validator_test.go @@ -310,6 +310,13 @@ func TestValidateFile(t *testing.T) { "field policy_templates.0.input: Must not be present", }, }, + "bad_input_template_path": { + "manifest.yml", + []string{ + "field policy_templates.0: template_path is required", + "policy template \"sql_query\" references template_path \"\": template_path is required for input type packages", + }, + }, } for pkgName, test := range tests { diff --git a/spec/changelog.yml b/spec/changelog.yml index 5b1a0f8e3..4bb7d273f 100644 --- a/spec/changelog.yml +++ b/spec/changelog.yml @@ -20,6 +20,9 @@ - description: Add support for script testing in data streams. type: enhancement link: https://github.com/elastic/package-spec/pull/985 + - description: Input packages require to define template_path in manifest. + type: enhancement + link: https://github.com/elastic/package-spec/pull/1000 - version: 3.5.0 changes: - description: Add `duration` variable data type with `min_duration` and `max_duration` validation properties. diff --git a/spec/input/manifest.spec.yml b/spec/input/manifest.spec.yml index 926ea0a5b..ecce958dc 100644 --- a/spec/input/manifest.spec.yml +++ b/spec/input/manifest.spec.yml @@ -94,6 +94,7 @@ spec: - description - type - input + - template_path icons: $ref: "../integration/manifest.spec.yml#/definitions/icons" screenshots: diff --git a/test/packages/bad_duplicated_fields_input/manifest.yml b/test/packages/bad_duplicated_fields_input/manifest.yml index 1158d13b0..988f863b3 100644 --- a/test/packages/bad_duplicated_fields_input/manifest.yml +++ b/test/packages/bad_duplicated_fields_input/manifest.yml @@ -27,6 +27,7 @@ policy_templates: type: logs input: log_file description: Collect sample logs + template_path: input.yml.hbs vars: - name: paths required: true diff --git a/test/packages/bad_input_template_path/LICENSE.txt b/test/packages/bad_input_template_path/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/test/packages/bad_input_template_path/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/test/packages/bad_input_template_path/_dev/build/build.yml b/test/packages/bad_input_template_path/_dev/build/build.yml new file mode 100644 index 000000000..df467d35b --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/build/build.yml @@ -0,0 +1,4 @@ +dependencies: + ecs: + reference: git@v1.9.2 + import_mappings: false \ No newline at end of file diff --git a/test/packages/bad_input_template_path/_dev/build/docs/README.md b/test/packages/bad_input_template_path/_dev/build/docs/README.md new file mode 100644 index 000000000..1a9dfb44c --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/build/docs/README.md @@ -0,0 +1 @@ +This is a template for the package README. \ No newline at end of file diff --git a/test/packages/bad_input_template_path/_dev/deploy/tf/.terraform.lock.hcl b/test/packages/bad_input_template_path/_dev/deploy/tf/.terraform.lock.hcl new file mode 100644 index 000000000..fbb6f39c1 --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/deploy/tf/.terraform.lock.hcl @@ -0,0 +1,8 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/google" { +} + +provider "registry.terraform.io/hashicorp/local" { +} diff --git a/test/packages/bad_input_template_path/_dev/deploy/tf/data.json b/test/packages/bad_input_template_path/_dev/deploy/tf/data.json new file mode 100644 index 000000000..ada45b78f --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/deploy/tf/data.json @@ -0,0 +1,3 @@ +{ + "a": "data file containing json" +} diff --git a/test/packages/bad_input_template_path/_dev/deploy/tf/main.tf b/test/packages/bad_input_template_path/_dev/deploy/tf/main.tf new file mode 100644 index 000000000..f6a81b458 --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/deploy/tf/main.tf @@ -0,0 +1 @@ +# A Terraform file diff --git a/test/packages/bad_input_template_path/_dev/deploy/tf/template.tftpl b/test/packages/bad_input_template_path/_dev/deploy/tf/template.tftpl new file mode 100644 index 000000000..d9e45e2a0 --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/deploy/tf/template.tftpl @@ -0,0 +1 @@ +A Terraform template file diff --git a/test/packages/bad_input_template_path/_dev/test/config.yml b/test/packages/bad_input_template_path/_dev/test/config.yml new file mode 100644 index 000000000..08b057dc1 --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/config.yml @@ -0,0 +1,7 @@ +system: + parallel: true +policy: + parallel: false + skip: + reason: ignoring all system tests + link: https://github.com/elastic/package-spec/issues/1 diff --git a/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.expected b/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.expected new file mode 100644 index 000000000..ae8f7b32c --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.expected @@ -0,0 +1,39 @@ +inputs: + - data_stream: + namespace: ep + meta: + package: + name: sql_input + name: test-mysql-sql_input + streams: + - data_stream: + dataset: sql_input.sql_query + elasticsearch: + dynamic_dataset: true + dynamic_namespace: true + type: metrics + driver: mysql + hosts: + - root:test@tcp(localhost:3306)/ + metricsets: + - query + period: 10s + sql_query: SHOW GLOBAL STATUS LIKE 'Innodb_%'; + sql_response_format: variables + type: sql/metrics + use_output: default +output_permissions: + default: + _elastic_agent_checks: + cluster: + - monitor + _elastic_agent_monitoring: + indices: [] + uuid-for-permissions-on-related-indices: + indices: + - names: + - metrics-*-* + privileges: + - auto_configure + - create_doc +secret_references: [] diff --git a/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.yml b/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.yml new file mode 100644 index 000000000..045b81d07 --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/policy/test-mysql.yml @@ -0,0 +1,4 @@ +vars: + hosts: + - root:test@tcp(localhost:3306)/ + sql_query: "SHOW GLOBAL STATUS LIKE 'Innodb_%';" diff --git a/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.expected b/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.expected new file mode 100644 index 000000000..2d92b5a7f --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.expected @@ -0,0 +1,39 @@ +inputs: + - data_stream: + namespace: ep + meta: + package: + name: sql_input + name: test-oracle-sql_input + streams: + - data_stream: + dataset: sql_input.sql_query + elasticsearch: + dynamic_dataset: true + dynamic_namespace: true + type: metrics + driver: oracle + hosts: + - root:test@tcp(localhost)/ + metricsets: + - query + period: 10s + sql_query: SELECT file_name, file_id, tablespace_name, bytes, status, maxbytes, user_bytes, online_status FROM sys.dba_data_files + sql_response_format: variables + type: sql/metrics + use_output: default +output_permissions: + default: + _elastic_agent_checks: + cluster: + - monitor + _elastic_agent_monitoring: + indices: [] + uuid-for-permissions-on-related-indices: + indices: + - names: + - metrics-*-* + privileges: + - auto_configure + - create_doc +secret_references: [] diff --git a/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.yml b/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.yml new file mode 100644 index 000000000..7e349bd4e --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/policy/test-oracle.yml @@ -0,0 +1,6 @@ +vars: + driver: "oracle" + hosts: + - root:test@tcp(localhost)/ + # FIXME: This doesn't work as a multiline block. + sql_query: SELECT file_name, file_id, tablespace_name, bytes, status, maxbytes, user_bytes, online_status FROM sys.dba_data_files diff --git a/test/packages/bad_input_template_path/_dev/test/system/test-default-config.yml b/test/packages/bad_input_template_path/_dev/test/system/test-default-config.yml new file mode 100644 index 000000000..b44bf03ac --- /dev/null +++ b/test/packages/bad_input_template_path/_dev/test/system/test-default-config.yml @@ -0,0 +1,2 @@ +wait_for_data_timeout: 10m +vars: ~ diff --git a/test/packages/bad_input_template_path/agent/input/input.yml.hbs b/test/packages/bad_input_template_path/agent/input/input.yml.hbs new file mode 100644 index 000000000..6eb03670b --- /dev/null +++ b/test/packages/bad_input_template_path/agent/input/input.yml.hbs @@ -0,0 +1,9 @@ +metricsets: ["query"] +period: {{period}} +hosts: +{{#each hosts}} + - {{this}} +{{/each}} +driver: {{driver}} +sql_query: {{sql_query} +sql_response_format: {{sql_response_format}} \ No newline at end of file diff --git a/test/packages/bad_input_template_path/changelog.yml b/test/packages/bad_input_template_path/changelog.yml new file mode 100644 index 000000000..945b7a373 --- /dev/null +++ b/test/packages/bad_input_template_path/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "1.0.0" + changes: + - description: Initial draft of the package + type: enhancement + link: https://github.com/elastic/package-spec/pull/455 diff --git a/test/packages/bad_input_template_path/docs/README.md b/test/packages/bad_input_template_path/docs/README.md new file mode 100644 index 000000000..2023396ba --- /dev/null +++ b/test/packages/bad_input_template_path/docs/README.md @@ -0,0 +1 @@ +# SQL Input \ No newline at end of file diff --git a/test/packages/bad_input_template_path/docs/knowledge_base/README.md b/test/packages/bad_input_template_path/docs/knowledge_base/README.md new file mode 100644 index 000000000..5e5d0214e --- /dev/null +++ b/test/packages/bad_input_template_path/docs/knowledge_base/README.md @@ -0,0 +1,12 @@ +# Knowledge Base Directory + +This directory contains markdown files that provide AI assistant context for the integration. + +Markdown files in this directory will be available to AI assistants to provide context when users ask questions about this integration. This helps improve the quality and accuracy of AI-generated responses about the integration. + +## Guidelines for creating knowledge base files + +1. Files must be in markdown format with the `.md` extension +2. Files can have any name, but should be descriptive +3. Nested directories are not allowed +4. Content should be focused on providing helpful context about the integration diff --git a/test/packages/bad_input_template_path/docs/knowledge_base/example.md b/test/packages/bad_input_template_path/docs/knowledge_base/example.md new file mode 100644 index 000000000..15e044814 --- /dev/null +++ b/test/packages/bad_input_template_path/docs/knowledge_base/example.md @@ -0,0 +1,19 @@ +# Example Knowledge Base Content + +This is an example knowledge base article in markdown format for the Elastic integration. + +## Features + +- Provides context to AI assistants +- Supports markdown formatting +- Can include code examples + +```python +def example_function(): + print("This is an example function") + return True +``` + +## Usage + +This knowledge base article can be referenced by AI assistants to help users troubleshoot and understand the integration. diff --git a/test/packages/bad_input_template_path/fields/base-fields.yml b/test/packages/bad_input_template_path/fields/base-fields.yml new file mode 100644 index 000000000..7c798f453 --- /dev/null +++ b/test/packages/bad_input_template_path/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_input_template_path/fields/input.yml b/test/packages/bad_input_template_path/fields/input.yml new file mode 100644 index 000000000..66f3bf3cb --- /dev/null +++ b/test/packages/bad_input_template_path/fields/input.yml @@ -0,0 +1,7 @@ +- name: input.name + type: constant_keyword + description: Sample field to be added. + value: logs +- name: foo + runtime: true + type: keyword diff --git a/test/packages/bad_input_template_path/img/sample-logo.svg b/test/packages/bad_input_template_path/img/sample-logo.svg new file mode 100644 index 000000000..6268dd88f --- /dev/null +++ b/test/packages/bad_input_template_path/img/sample-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/packages/bad_input_template_path/img/sample-screenshot.png b/test/packages/bad_input_template_path/img/sample-screenshot.png new file mode 100644 index 000000000..d7a56a3ec Binary files /dev/null and b/test/packages/bad_input_template_path/img/sample-screenshot.png differ diff --git a/test/packages/bad_input_template_path/lifecycle.yml b/test/packages/bad_input_template_path/lifecycle.yml new file mode 100644 index 000000000..b56a81e81 --- /dev/null +++ b/test/packages/bad_input_template_path/lifecycle.yml @@ -0,0 +1 @@ +data_retention: "30d" diff --git a/test/packages/bad_input_template_path/manifest.yml b/test/packages/bad_input_template_path/manifest.yml new file mode 100644 index 000000000..5bc5afc57 --- /dev/null +++ b/test/packages/bad_input_template_path/manifest.yml @@ -0,0 +1,105 @@ +format_version: 2.12.0 +name: good_input +title: good_input +description: >- + Execute custom queries against an SQL database and store the results in Elasticsearch. +type: input +version: 1.0.0 +source: + license: "Apache-2.0" +conditions: + elastic.subscription: basic + elastic.capabilities: [observability] + kibana: + version: "^8.10.0" +categories: + - custom + - datastore +policy_templates: + - name: sql_query + type: metrics + title: SQL Query + description: Query the database to capture metrics. + input: sql + fips_compatible: false + vars: + - name: hosts + type: text + title: Hosts + multi: true + required: true + show_user: true + default: + - http://127.0.0.1 + - name: password + type: password + title: Password + show_user: true + secret: true + - name: period + type: text + title: Period + multi: false + required: true + show_user: true + default: 10s + - name: driver + type: text + title: Driver + description: "Supported database drivers: mssql, mysql, oracle, postgres" + multi: false + required: true + show_user: true + default: "mysql" + - name: sql_query + type: text + title: Query + multi: false + required: true + show_user: true + default: "SHOW GLOBAL STATUS LIKE 'Innodb_system%'" + - name: sql_response_format + type: text + title: Response format + description: "Supported response formats: variables, table" + multi: false + 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" +screenshots: + - src: "/img/sample-screenshot.png" + title: "Sample screenshot" + size: "600x600" + type: "image/png" +owner: + github: elastic/integrations +agent: + privileges: + root: true +elasticsearch: + index_template: + mappings: + properties: + '@timestamp': + ignore_malformed: false + type: date + dynamic_templates: + - data_stream_to_constant: + mapping: + type: constant_keyword + path_match: data_stream.* diff --git a/test/packages/bad_input_template_path/sample_event.json b/test/packages/bad_input_template_path/sample_event.json new file mode 100644 index 000000000..617212c23 --- /dev/null +++ b/test/packages/bad_input_template_path/sample_event.json @@ -0,0 +1,63 @@ +{ + "@timestamp": "2022-11-16T19:00:58.919Z", + "agent": { + "ephemeral_id": "1f2789fe-4041-4b4d-aac2-076a34c5d24f", + "id": "47bdbac3-731d-4b11-9af6-06fba253dba8", + "name": "docker-fleet-agent", + "type": "metricbeat", + "version": "8.5.0" + }, + "data_stream": { + "dataset": "good_input.sql_query", + "namespace": "ep", + "type": "metrics" + }, + "ecs": { + "version": "8.0.0" + }, + "elastic_agent": { + "id": "47bdbac3-731d-4b11-9af6-06fba253dba8", + "snapshot": true, + "version": "8.5.0" + }, + "event": { + "dataset": "good_input.sql_query", + "duration": 1326395, + "module": "sql" + }, + "host": { + "architecture": "x86_64", + "containerized": false, + "hostname": "docker-fleet-agent", + "id": "0addaca3101a43f4a52be882837fb33d", + "ip": [ + "192.168.192.7" + ], + "mac": [ + "02-42-C0-A8-C0-07" + ], + "name": "docker-fleet-agent", + "os": { + "codename": "focal", + "family": "debian", + "kernel": "5.15.0-50-generic", + "name": "Ubuntu", + "platform": "ubuntu", + "type": "linux", + "version": "20.04.5 LTS (Focal Fossa)" + } + }, + "metricset": { + "name": "query", + "period": 10000 + }, + "service": { + "address": "elastic-package-service-good_input-1:3306", + "type": "sql" + }, + "sql": { + "driver": "mysql", + "metrics": {}, + "query": "SHOW GLOBAL STATUS LIKE 'Innodb_system%'" + } +} \ No newline at end of file diff --git a/test/packages/missing_required_fields_input/manifest.yml b/test/packages/missing_required_fields_input/manifest.yml index b87198d56..feadc48c3 100644 --- a/test/packages/missing_required_fields_input/manifest.yml +++ b/test/packages/missing_required_fields_input/manifest.yml @@ -27,6 +27,7 @@ policy_templates: input: log_file title: Sample logs description: Collect sample logs + template_path: input.yml.hbs vars: - name: paths required: true