From 0dcd64df4528bf6e3a2ac044b046480731f268ae Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 08:58:34 +0100 Subject: [PATCH 1/7] [CI] Add E2E for x-pack/elastic-agent (fleet) (#24112) (#28465) (cherry picked from commit a2fde7209fcea8da38a63f1076a6077476145067) Co-authored-by: Victor Martinez --- Jenkinsfile | 69 ++++++++++++++++++++-------- x-pack/elastic-agent/Jenkinsfile.yml | 4 +- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index eb36447753c6..ccb0097481ac 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -511,15 +511,25 @@ def getBeatsName(baseDir) { return baseDir.replace('x-pack/', '') } +/** +* This method runs the end 2 end testing +*/ +def e2e(Map args = [:]) { + if (!args.e2e?.get('enabled', false)) { return } + if (args.e2e.get('entrypoint', '')?.trim()) { + e2e_with_entrypoint(args) + } else { + e2e_with_job(args) + } +} + /** * This method runs the end 2 end testing in the same worker where the packages have been * generated, this should help to speed up the things */ -def e2e(Map args = [:]) { - def enabled = args.e2e?.get('enabled', false) +def e2e_with_entrypoint(Map args = [:]) { def entrypoint = args.e2e?.get('entrypoint') def dockerLogFile = "docker_logs_${entrypoint}.log" - if (!enabled) { return } dir("${env.WORKSPACE}/src/github.com/elastic/e2e-testing") { // TBC with the target branch if running on a PR basis. git(branch: 'master', credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken', url: 'https://github.com/elastic/e2e-testing.git') @@ -533,19 +543,46 @@ def e2e(Map args = [:]) { "LOG_LEVEL=TRACE"]) { def status = 0 filebeat(output: dockerLogFile){ - status = sh(script: ".ci/scripts/${entrypoint}", - label: "Run functional tests ${entrypoint}", - returnStatus: true) - } - junit(allowEmptyResults: true, keepLongStdio: true, testResults: "outputs/TEST-*.xml") - archiveArtifacts allowEmptyArchive: true, artifacts: "outputs/TEST-*.xml" - if (status != 0) { - error("ERROR: functional tests for ${args?.directory?.trim()} has failed. See the test report and ${dockerLogFile}.") + try { + sh(script: ".ci/scripts/${entrypoint}", label: "Run functional tests ${entrypoint}") + } finally { + junit(allowEmptyResults: true, keepLongStdio: true, testResults: "outputs/TEST-*.xml") + archiveArtifacts allowEmptyArchive: true, artifacts: "outputs/TEST-*.xml" + } } } } } +/** +* This method triggers the end 2 end testing job. +*/ +def e2e_with_job(Map args = [:]) { + def jobName = args.e2e?.get('job') + def testMatrixFile = args.e2e?.get('testMatrixFile', '') + def notifyContext = "e2e-${args.context}" + def e2eTestsPipeline = "${jobName}/${isPR() ? "${env.CHANGE_TARGET}" : "${env.JOB_BASE_NAME}"}" + + def parameters = [ + booleanParam(name: 'forceSkipGitChecks', value: true), + booleanParam(name: 'forceSkipPresubmit', value: true), + booleanParam(name: 'notifyOnGreenBuilds', value: !isPR()), + string(name: 'BEAT_VERSION', value: "${env.VERSION}-SNAPSHOT"), + string(name: 'testMatrixFile', value: testMatrixFile), + string(name: 'GITHUB_CHECK_NAME', value: notifyContext), + string(name: 'GITHUB_CHECK_REPO', value: env.REPO), + string(name: 'GITHUB_CHECK_SHA1', value: env.GIT_BASE_COMMIT), + ] + + build(job: "${e2eTestsPipeline}", + parameters: parameters, + propagate: false, + wait: false + ) + + githubNotify(context: "${notifyContext}", description: "${notifyContext} ...", status: 'PENDING', targetUrl: "${env.JENKINS_URL}search/?q=${e2eTestsPipeline.replaceAll('/','+')}") +} + /** * This method runs the given command supporting two kind of scenarios: * - make -C then the dir(location) is not required, aka by disaling isMage: false @@ -578,19 +615,15 @@ def target(Map args = [:]) { cmd(label: "${args.id?.trim() ? args.id : env.STAGE_NAME} - ${command}", script: "${command}") } } - // TODO: - // Packaging should happen only after the e2e? + // Publish packages should happen always to easily consume those artifacts if the + // e2e were triggered and failed. if (isPackaging) { publishPackages("${directory}") + pushCIDockerImages(beatsFolder: "${directory}", arch: dockerArch) } if(isE2E) { e2e(args) } - // TODO: - // push docker images should happen only after the e2e? - if (isPackaging) { - pushCIDockerImages(beatsFolder: "${directory}", arch: dockerArch) - } } } } diff --git a/x-pack/elastic-agent/Jenkinsfile.yml b/x-pack/elastic-agent/Jenkinsfile.yml index 5cf3a25e1719..23a5daf0a6f8 100644 --- a/x-pack/elastic-agent/Jenkinsfile.yml +++ b/x-pack/elastic-agent/Jenkinsfile.yml @@ -95,7 +95,9 @@ stages: packaging-linux: packaging-linux: "mage package" e2e: - enabled: false + enabled: true + job: 'e2e-tests/e2e-testing-mbp' + testMatrixFile: '.ci/.e2e-tests-for-elastic-agent.yaml' stage: packaging packaging-arm: packaging-arm: "mage package" From acfdf978a23f87efced9951146a195bdd9dae9b2 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 09:00:23 +0100 Subject: [PATCH 2/7] Register `storage_account` as second name for `storage` metricset (#28447) (#28470) * add storage * changelog * add fields (cherry picked from commit b3991d4b0b93ce9122ff7cf1ad2ba56d9dc91ed6) Co-authored-by: Mariana Dima --- CHANGELOG.next.asciidoc | 1 + metricbeat/docs/fields.asciidoc | 10 ++++++++++ x-pack/metricbeat/module/azure/fields.go | 2 +- .../metricbeat/module/azure/storage/_meta/fields.yml | 7 +++++++ x-pack/metricbeat/module/azure/storage/storage.go | 1 + 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 305c2fb59a29..ba176989a00f 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -509,6 +509,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Fix release state of kubernetes metricsets. {pull}26864[26864] - Add `gke` metricset collection to `gcp` module {pull}26824[26824] - Added a new beta `enterprisesearch` module for Elastic Enterprise Search {pull}27549[27549] +- Register additional name for `storage` metricset in the azure module. {pull}28447[28447] *Packetbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 0e5321338912..f63c7bacd912 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -6203,6 +6203,16 @@ monitor storage account +type: object + +-- + +*`azure.storage_account.*.*`*:: ++ +-- +storage account + + type: object -- diff --git a/x-pack/metricbeat/module/azure/fields.go b/x-pack/metricbeat/module/azure/fields.go index 8f3ddad984c9..b5165fc5a679 100644 --- a/x-pack/metricbeat/module/azure/fields.go +++ b/x-pack/metricbeat/module/azure/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAzure returns asset data. // This is the base64 encoded zlib format compressed contents of module/azure. func AssetAzure() string { - return "eJzkmc9u67YSxvd5ikGWAU4ewIsL5LZdnEXRon/WxJgaK2wkkoccOsd9+oKiJMuSLMu27CaoFwZiUd/vG3JmJDJf4I12K8C/g6MHAFZc0AoeX+Lfjw8AGXnplGVl9Ar+9wAAaSyUJgtFvMVRQehpBTk+AGwUFZlfVQO/gMaS9uLxwzsbhzoTbP3LCOFQpivFqqTcodLtlUbyjXbvxmWd30eF0+ePV4KXFAaxU3JEtyE68iY4SQNgN4YZuEYHvCWpNoq6VvvhHoS8s3Rw4XjEJ2w0VuLtYDbAHVuj6Pi9LDoqzkL3Z3cBdrsCQ+12rjH3z0+jWLP+iyT3LqUfxZSxzhBRorVK5/X4x6fH84JIGduGUZkd5Gv89hZHEvbsCmmlwFNBkjsp29B8WLcSQmXXM7uC8PXHARCtLZTExXgdvTFcpkrSXhl9mBZHUuJEOsxNhQnLB02rY25gPA3xz09n+94UBo9cvNT1z8kMOOLgNGVDu2itUNqr/JX9yU7bPnHWxDjPQXeZRzhT/dczOhYZ8ngrHLkwoxdVosN7GybpbGki6ew4bzxb4Izm188aWLT1xQBqj6Op4/kwspvkTR/yX08aR98CefZCmqD52YdylDyWGSfQvyVlqISn2RtUBWW3gCflCQ/Bk2uCD1p9C+Mzf4GFPz25CbAnX3X9m7B/T+In48bAr6Q5FgdlC3t46Won3oSftTPvnpxgVSqde6GJ3417E1lwVeE+4zZfytn/EwtqFtQsaFizDPqqUu/gzlf1e441R5LUlsQdzNWo8/xZZ2RMUJ3fZQL3uPNssmEs7uKwIk2bo++SKr0bdOqfGu2J+uzw63m6oQNAblYDCtpSccqSJ7e9uaMEmTBkyW2MK1FLSosUW2xJpXE7gVtUBa4LEusdk18ym37dY6HBQsJCi4UKO992XTTCOrVFvpfrmgo19VLT0gZhyUnSjDmlQr6bd2kD7OGptq8N4V8yf7ZtZaoVi86FJ2l0djfnX39J2RL9QWIPdhlrVRRK57fYY9TSgDq+68SFz4hRFXM3qDI4R1ruRufq4tOyUdV2IR0xfhfS+P46XLxCP/S12iMYsui4JM1i+fPIvfjwsHMfrMnCYPd7JbgWHZ7u7t+yY/+ptnwLbuhSfp3YSCY06X5Y14Mn95N1HcQOoEx2eLoH1894U2ZJHnry7WmCrNrDDVKtLfNEOJ5vKDlgsWhxVSedlSwMZBvsxjiS6HlxcCN8HJ0SbuGzi7qVdu9tO6YpbWAS27J34nX4v6xDF3c/Nd27nAhAeIkFeeLPEUlrt70+EptmVJqcUNpzfGJ/7NBqt9C4nQjIUa48u93nCKhxOxFQ3Neoz7JAtdlBOBkyrtGTqDvzR46m8do8RQbBlEYrNm7+e2o+8y11KNx/Jz1e0p6Ni1uRDzyxtcV2Xv8JAAD//1lC3T4=" + return "eJzkmc9u67YSxvd5ikGWAU4ewIsL5LZdnEXRon/WxJgaK2wkkoccOsd9+oKiJMuSLMu27CaoFwZiSt/vG3JmJDJf4I12K8C/g6MHAFZc0AoeX+Lfjw8AGXnplGVl9Ar+9wAA6VooTRaKeIujgtDTCnJ8ANgoKjK/qi78AhpL2ovHD+9svNSZYOtfRgiHMl0pViXlDpVuRxrJN9q9G5d1fh8VTp8/XgleUhjETskR3YboyJvgJA2A3Rhm4Bod8Jak2ijqWu2HexDyztLBwPGIT9horMTbwWyAO7ZG0fF7WXRUnIXuz+4C7HYFhtrtXGPun59GsWb9F0nuDaUfxZSxziWiRGuVzuvrH58ezwsiZWwbRmV2kK/x21scSdizK6SVAk8FSe6kbEPzYd1KCJVdz+wKwtcfB0C0tlASF+N19MZwmSpJe2X0YVocSYkT6TA3FSYsHzStjrmB8XSJf3462/emMHhk8FLXPycz4IiD05QN7aK1Qmmv8lf2Jztt+8RZE+M8B91lHuFM9V/P6FhkyOOtcGRgRi+qRIf3NkzS2dJE0tlx3ni2wBnNr581sGjriwHUHkdTx/NhZDfJmz7kv540jr4F8uyFNEHzsw/lKHksM06gf0vKUAlPszeoCspuAU/KEx6CJ9cEH7T6FsZn/gILf3pyE2BPvur6N2H/nsRPxo2BX0lzLA7KFvbw0tVOvAk/a2fePTnBqlQ690ITvxv3JrLgqsJ9xm2+lLP/JxbULKhZ0LBmGfRVpd7Bna/q9xxrjiSpLYk7mKtR5/mzzsiYoDq/ywTucefZZMNY3MVhRZo2R98lVXo36NQ/NdoT9dnh1/N0QweA3KwGFLSl4pQlT257c0cJMmHIktsYV6KWlBYpttiSSuN2AreoClwXJNY7Jr9kNv26x0KDhYSFFgsVdr7tumiEdWqLfC/XNRVq6qWmpQ3CkpOkGXNKhXw379IG2MNTbV8bwr9k/mzbylQrFp0LT9Lo7G7Ov/6SsiX6g8Qe7DLWqiiUzm+xx6ilAXV814kLnxGjKuZuUGVwjrTcjc7Vxadlo6rtQjpi/C6k8f11uHiFfuhrtUcwZNFxSZrF8ueRe/HhYec+WJOFwe73SnAtOjzd3b9lx/5TbfkW3NCl/DqxkUxo0v2wrgdP7ifrOogdQJns8HQPrp/xpsySPPTk29MEWbWHG6RaW+aJcDzfUHLAYtHiqk46K1kYyDbYjXEk0fPi4Eb4ODol3MJnF3Ur7d7bdkxT2sAktmXvxOvwf1mHLu5+arp3ORGA8BIL8sSfI5LWbjs+EptmVJqcUNpzfGJ/7NBqt9C4nQjIUa48u93nCKhxOxFQ3Neoz7JAtdlBOBkyrtGTqDvzR46m8do8RQbBlEYrNm7+e2o+8y11KNx/Jz1e0p6Ni1uRDzyxtcWj81qPf4Yc6YfyTwAAAP//nCIVNA==" } diff --git a/x-pack/metricbeat/module/azure/storage/_meta/fields.yml b/x-pack/metricbeat/module/azure/storage/_meta/fields.yml index 0e699901c8a9..1e6437288902 100644 --- a/x-pack/metricbeat/module/azure/storage/_meta/fields.yml +++ b/x-pack/metricbeat/module/azure/storage/_meta/fields.yml @@ -5,3 +5,10 @@ object_type_mapping_type: "*" description: > storage account +- name: storage_account.*.* + release: ga + type: object + object_type: float + object_type_mapping_type: "*" + description: > + storage account diff --git a/x-pack/metricbeat/module/azure/storage/storage.go b/x-pack/metricbeat/module/azure/storage/storage.go index 4178b911d117..1869dea92942 100644 --- a/x-pack/metricbeat/module/azure/storage/storage.go +++ b/x-pack/metricbeat/module/azure/storage/storage.go @@ -24,6 +24,7 @@ var ( // MetricSet has been created then Fetch will begin to be called periodically. func init() { mb.Registry.MustAddMetricSet("azure", "storage", New) + mb.Registry.MustAddMetricSet("azure", "storage_account", New) } // MetricSet holds any configuration or state information. It must implement From 49d34f9b328b1c5b9cd8ac41a6932b6fe63ced36 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 11:38:28 +0200 Subject: [PATCH 3/7] Run Python tests in libbeat (#28438) (#28485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit ce29bea6a1d901c45a861d72fdafe2b469272a5d) Co-authored-by: Noémi Ványi --- libbeat/Jenkinsfile.yml | 3 + libbeat/magefile.go | 1 + libbeat/tests/files/testbeat-dashboards.zip | Bin 19119 -> 43877 bytes libbeat/tests/system/test_dashboard.py | 177 ++------------------ 4 files changed, 20 insertions(+), 161 deletions(-) diff --git a/libbeat/Jenkinsfile.yml b/libbeat/Jenkinsfile.yml index b97771161451..4ef08116814a 100644 --- a/libbeat/Jenkinsfile.yml +++ b/libbeat/Jenkinsfile.yml @@ -37,6 +37,9 @@ stages: goIntegTest: mage: "mage goIntegTest" stage: mandatory + pythonIntegTest: + mage: "mage pythonIntegTest" + stage: mandatory crosscompile: make: "make -C libbeat crosscompile" stage: mandatory diff --git a/libbeat/magefile.go b/libbeat/magefile.go index eddc4f5e7aae..937b3f880015 100644 --- a/libbeat/magefile.go +++ b/libbeat/magefile.go @@ -36,6 +36,7 @@ import ( func init() { unittest.RegisterPythonTestDeps(Fields) integtest.RegisterGoTestDeps(Fields) + integtest.RegisterPythonTestDeps(Fields) } // Build builds the Beat binary. diff --git a/libbeat/tests/files/testbeat-dashboards.zip b/libbeat/tests/files/testbeat-dashboards.zip index 1a68706ed71902a48333cbda29159794edf60d27..78c185faaafdd372921e941c9f5c6c82f4ab556d 100644 GIT binary patch literal 43877 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

+46r)5jdo=7AumCNkjW) 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%0AH^&jCV-X1tDk z$V_#)3tJxBVyy;fu~{<~u5+vSEn=gxw)V@VUbF6xj{_5YeeS(S!F?2KU>~%C)I9rq z_Ak~v+}kmxHf0nf##kS)TSRb5svC&~#AqsX79G9;W@#J^QLL|SpiYy5#Hoya1|%Io7aPt_%vsp1 zC!g*Ptwlz5;$|(A$mf*Xq%91}(KimeDGC=(t+^J32d$~9!ML~9yV*xkTABD9x@BTRrz3!u$ z@6+pF7;mYm_~wIiqrI2iu@p~wo@h(mL@z0qR56ET3Cp$ zzzZmwkB`YT=}#Hu_Scl!xenkkmfKX=!St9~DMTT7_%5*L)$y&aYg~;98F$S?u6r4Q@ z1$zHj5^d$mbTfL`K?;%39o2Xkm}HwzT8s;1>N7-xXJI_cT}Kl+ zYg(={99e4~KVQ>>a=nPF(-2~`oiEQuh94^-1+TNNwb108D?F3nxbSfXBC-M*&B%ro z_p_|`7FH37Zojs8rO1pGi2I1p21pUjHSnaFkz0CFDQfZ}5}9}lG^9W2lXEPc-7QOB z(e}){{nEz&%pu2c)q{@Tkq_gPhiBHY?$3F&%?}C!auQRand*cfOKI`d)=zW(NJXC& z;~X-nZ0DM8(>&?jb}CL1Ztu&|m&)z?sh;mkSX?-{NvZh>Z+?5Ayah3r_0Uy>dVCG; zyt6JK;NF9B&bCmiVG8>kXy(QpF~k~E;g>rxfh0_`yX@)?my+?s6Z!mXo(x=CP zH5)-`c#|xdZxlH9fRK7o#P2Kux2i;? z(r5#SwpX-O1FF^rkfF$MJ>z2LPujoK0l)hhXwcJIc9GcPMUAQYLs#Qwvgrzx8Gv{T zGsb((g}?aJ(OYPHV<=0oe5+b6mUZ%>9GtEfe(DhK^Y>CuSSt-E2MUNs6>^*PgW9zm zhH!KrB&`WvV$n`zx~%A&Ii5A!eTC%oyh@eqQ5uSxm}(=CtT}Ba?ah-~bhl=IM(KZD zer^C~>0)e_mYw7+847X&t%H%a60ys5!B4OPk!B z4sH}J(xSY$_I1DS`5J`Yepl6PJ%NAr-M9*IWvA&;>klCOvB|U>ZHxbS-}3b@CV83w zR#}uF?YG`RG$T1f8P53`cDBCXSv*}1?(aYbQxEEoZsx>#x>7O~hC zER5{1z|I1SfIJ#hY_|v@^)Wj;+xjR9i|_b~7+2m6{=uc6Vm_&jagANO{%rV z+E^l5#ir>)jW+l~Y|rfM!Wr&`K}#a}!X_=6)ec}T&Ljef7(@PFTw$e(G?5WZa@o(!Hgo8R-1OOk@R9=mp4xVt9( zyM;CRml7K)*0go})*11I@^tvGe`l2Bw`9Tf&TZvhwU!`Dv$N%^b4xDI%D&?1Pgo!Q z(YNK+>tl)@nJ8_U5OiviVZ-&7kU>>E|1jv4K<#sMK#bLz6BAE(xrr0l z=8JplD>e>mui6$F;;gSdo$HEexo+H4+V&(h?e62*0ryT97JZVr{n_`8#fLj!ciVYv z#DfL?mCGdY6o28;y5j1Fk%pTu?uBt0^xSAa?Nnf4)~;OWRrgy62UF#KGjO-l)Gx{u zXPHfr%6Plv{J^$QDz!V|#NlAhudpelsMjFjD@VhqYFE-ehUu=X{)%>G@6WUngUDIM zC3+v34A+%7;H!jLD`FreG`PstRe4tYIL7IUJo8##tp5wZ@zEgH^-3rZqyi8n*i zo7wCDPb0xB+CuJPIZrSpYe_9AW;+NAbZB|#X4U98*{y)nUQV>>ZH9UFu|WEE zSS%({klk8URRp9a6oUP^%qw<_#b%QwDL&4dPzY>d{}X%%*kV@hDA^2bk#02-X4^5G zkxj6G3!lm6HsSE3VoQpWz&q@+D8$LK39=M>#>mw_+o!I*f%E+b|9Y&)dtIq{N>|bvN^HxfVXz+7^ z%w5OxmJ-IuCJj7=9oQ%d?3j&AuEuP;#xSxmU8#6|;pzGO{rwumT$;eHF8jQInXh=}ks9YahXr0740!#2{q!AO?x!89^9=2!V|f zLWtSOL^sT~)X2!jknaX;lx#Q5MuuBqwt#p>HioDxV57ubVKy@62eW-?v2w<2q}wfKOP<2W#^8Mm zY!u&H%to4*Vzz)hMm7d3Q(&|A|A!>$K8e}d-)3ZE@S+4ZAOG-?eu0?n{JV^74DNxz zMsW_rYf2ivVYa#gMz%if-++W-{f0?MlP^p%vFLx3P%OWIhGO@HX-JzUOcOMdk%qyv z3D_uxO_+_esljXq=P-P6{YclYcUyL-;Y##TjTWYiy5 zRNa|bnfcsLDawF?!2tbpXo{!F{9EP!Ezp3FfLzU7T#e0)TucKN+7!PJmnQ2{lW(A@LSLt1z9B-VGx zf%{KmI8Gq!BBvo0<`Gb6JEnC4mmf?bepKyC5Bi9!rCwXhSL-KwpWZ69ob;hc!jaEE zTiI~^pIAbX3?w-OJh^A(TAX+b7rJpIeEz93F%+tB7vo=@33ANkv;ZOy53*w^(Og=} z2W9$y4DB#RI&ZxR2;ICIK-~>$YNv?BeNDF6*FM_GX1a7?JlTRJc^Yy4qMKO=vM*}I zM%qWs0alcOgmPNamstHPEf^Nize)D*qSFSm%l~K5|0l`*qapsKKJecb_^;~!_-`nR z|3UqKq5exVfc@qDbN$1-%IJpq#fTO@6NL{#kB#5_0wiBoxJY>l%LzrVEHuj%Uw8Ey z;d!>ZSo96K2P-8{FJn(q^!V6-3{A2>{KLjeBBG_YHT~N4I*y8IQzcu1km2#K>`>sCm@=92vaqMSe1YAQS&)rP=0e?d>1i}65eG(>>n?SWaau+t46h%hyIa}FTO z8_;DY^cxw$e7^Q4&)ftEk2w^pEwHx&0=6EH-bwP!K2UZqMV!=z#Q*Ys#{dzlI6?j+ zH(IFf+ra-v?i=?l>HjP@;s2%)$G-&s^`ffvAASK_5Tk0*D(73#s2#!`tMkQ z{|i>m%+=Y-}u{C;D2jR7}jOE)JsUEqXEsK4t_ z0c!E^ScA7eE}2nKOEM2*4ML$UUoWS(gR{GrT%m}Q+EJX~QvkxI_VX;AxR1*AfPgvWX9pv+jn!9IEAJewSssg-8#bN1UZ7R6M(= zX~32j9TQqcK!Tw_O5AD2VD5Qw85xDo(s*>pX@i;Jz-(S!gr^6?GrV zE@@vat0dF2#6|`Fl)IR*`%nHEYC$&Yr1$jkBmVI!LKqJVAlAslzmV}Gqf839zFj+w z_Z`__Kegr$4QINg%eY$Ei&!C&a7>0}HR1&sz3Eg3^?ZK-^?5;L4P-{-8@YdScoTsc zkU(1Gwk@o!h0EAlDtS<}SH0!*`-l&wRA% zdlbzp3id%dQ9PV&*S_BN;R|I;S4x!m?fpGAbcTX z>OYm(AQ9`(7SVwg3U)Kk2_dc(q&Gl*wtNtFHFeGrG|Ta4+Qn&HD}B9l9ej&Xc&HllT-Gdi^DQk$n$n}nIg75MDyr0lj9C!!@!Wt zuoTe_u5lARo;?uHhQ&5(Gb&-l1~gMhrKk zeHZ*vBeNo_D4H#UF(zx;!{QUO_K?HKI2FPu5@X1IMVz5$6N3ZH=St#SCqdniYaEG$r1VeC8RRpW`F+VQ@1M-L=N>)?V4!Z_GPH6z z`a3x}J#9FUMfUZU3Vh#xyt)*^Cn;ATAn23SY?K`|62}fD><{FS!1{1DfE;#z5#IqG zc$f>wT6!EVv?RQkb0IUP4SNeASa`61C;#OAr%+|hs59%#i{Od)Gmi6HBJKO&*j@-L zSs#U`>~-_j&e=8UCIRlFnSH57AU){|E^8W0+Yv-ACMN39B8`5t4TvBUGMovR;E)a| z1elBnX!Vfo6|j-b4^;Uu`jYC+ipJ$+%Z0;YCyktY6ofLWTn7t(pxR zQ`fgMXK#q9S8A*K?lI8CCW9^b*0cFAO#K^pZ>EpXB{dw)vdV&fBS*7hs8 zWa3vEMI0u{STY@?LXJ40kEQwI;a#cYfV&};ifSBcTP%<`XvYGZfE7?!lIfS>gX_Q# zv#43|yjq^m6)G<-#!h3Q$i^$zxVL1vy3KfjH+vP{6p=2-$8plnT+fp3kN)IwS&rdx z%3gzfG~iK3*^|TMFM8kkWoUP2X$ASSaq3#0QXt|>V16Zd{&RYmxkV__89~$E@SyoQ z^WiFQdN~2hmSX#jx-&3ASs~QN2~kswj=E`g2*Y?yB%EP=s6Z>tA7g=TfgAVlZTFZk zh$i)fdCIS_6ef-;Kd>Nis(Rv(E1nG<;AK-5K4qJO*U{N;EPQ#*>Ia-bW=1mHXPHOE zNBz^Rlg2qTdH@a|wNIn{)~?x@8?<0{Uk0_y!j~lTt^KJpRvh}v>p3h$P3*1kTW}z( z1t!4K!E#MoGHzi_8FesMjAIDMvvS3Rx9)){UNr7?jef{H0B5)z_#d}wk#Q!d6riox?=ezapIn;86^vWZE?GE zdj-HpaxtQo=eC-;)`hr!cp~t^sU7OEc^=$*?1!F)%9lLQCNfU(hU7 z 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 BajpOW diff --git a/libbeat/tests/system/test_dashboard.py b/libbeat/tests/system/test_dashboard.py index 8022953042c3..338e832b0457 100644 --- a/libbeat/tests/system/test_dashboard.py +++ b/libbeat/tests/system/test_dashboard.py @@ -126,30 +126,6 @@ def test_load_only_index_patterns(self): assert self.log_contains("Kibana dashboards successfully loaded") is True - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_export_dashboard_cmd_export_dashboard_by_id_and_decoding(self): - """ - Test testbeat export dashboard can export dashboards - and removes unsupported characters - """ - self.render_config_template() - self.test_load_dashboard() - beat = self.start_beat( - logging_args=["-e", "-d", "*"], - extra_args=["export", - "dashboard", - "-E", "setup.kibana.protocol=http", - "-E", "setup.kibana.host=" + self.get_kibana_host(), - "-E", "setup.kibana.port=" + self.get_kibana_port(), - "-decode", - "-id", "Metricbeat-system-overview"] - ) - - beat.check_wait(exit_code=0) - - assert self.log_contains("\"id\": \"Metricbeat-system-overview\",") is True - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_export_dashboard_cmd_export_dashboard_by_id(self): @@ -165,12 +141,12 @@ def test_export_dashboard_cmd_export_dashboard_by_id(self): "-E", "setup.kibana.protocol=http", "-E", "setup.kibana.host=" + self.get_kibana_host(), "-E", "setup.kibana.port=" + self.get_kibana_port(), - "-id", "Metricbeat-system-overview"] + "-id", "Metricbeat-system-overview", + "-folder", "system-overview"] ) beat.check_wait(exit_code=0) - - assert self.log_contains("\"id\": \"Metricbeat-system-overview\",") is True + self._check_if_dashboard_exported("system-overview") @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -186,7 +162,8 @@ def test_export_dashboard_cmd_export_dashboard_by_id_unknown_id(self): "-E", "setup.kibana.protocol=http", "-E", "setup.kibana.host=" + self.get_kibana_host(), "-E", "setup.kibana.port=" + self.get_kibana_port(), - "-id", "No-such-dashboard"] + "-id", "No-such-dashboard", + "-folder", "system-overview"] ) beat.check_wait(exit_code=1) @@ -194,61 +171,6 @@ def test_export_dashboard_cmd_export_dashboard_by_id_unknown_id(self): expected_error = re.compile("error exporting dashboard:.*not found", re.IGNORECASE) assert self.log_contains(expected_error) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_export_dashboard_cmd_export_dashboard_from_yml(self): - """ - Test testbeat export dashboard can export dashboards from dashboards YAML file - and removes unsupported characters - """ - - self.render_config_template() - self.test_load_dashboard() - beat = self.start_beat( - logging_args=["-e", "-d", "*"], - extra_args=["export", - "dashboard", - "-E", "setup.kibana.protocol=http", - "-E", "setup.kibana.host=" + self.get_kibana_host(), - "-E", "setup.kibana.port=" + self.get_kibana_port(), - "-yml", os.path.join(self.beat_path, "tests", "files", "dashboards.yml")] - ) - - beat.check_wait(exit_code=0) - - version = self.get_version() - kibana_semver = semver.VersionInfo.parse(version) - exported_dashboard_path = os.path.join(self.beat_path, "tests", "files", "_meta", - "kibana", str(kibana_semver.major), "dashboard", "Metricbeat-system-test-overview.ndjson") - - with open(exported_dashboard_path) as f: - content = f.read() - assert "Metricbeat-system-overview" in content - - os.remove(exported_dashboard_path) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_export_dashboard_cmd_export_dashboard_from_not_existent_yml(self): - """ - Test testbeat export dashboard fails gracefully when cannot find YAML file - """ - - self.render_config_template() - beat = self.start_beat( - logging_args=["-e", "-d", "*"], - extra_args=["export", - "dashboard", - "-E", "setup.kibana.protocol=http", - "-E", "setup.kibana.host=" + self.get_kibana_host(), - "-E", "setup.kibana.port=" + self.get_kibana_port(), - "-yml", os.path.join(self.beat_path, "tests", "files", "no-such-file.yml")] - ) - - beat.check_wait(exit_code=1) - assert self.log_contains("Error exporting dashboards from yml") - assert self.log_contains("error opening the list of dashboards") - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_dev_tool_export_dashboard_by_id(self): @@ -258,60 +180,17 @@ def test_dev_tool_export_dashboard_by_id(self): self.test_load_dashboard() - path = os.path.normpath(self.beat_path + "/../dev-tools/cmd/dashboards/export_dashboards.go") - command = path + " -kibana http://" + self.get_kibana_host() + ":" + self.get_kibana_port() - command = "go run " + command + " -dashboard Metricbeat-system-overview" - - p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - content, err = p.communicate() - - assert p.returncode == 0 - - assert os.path.isfile("output.ndjson") is True - - with open('output.ndjson') as f: - content = f.read() - assert "Metricbeat-system-overview" in content - - os.remove("output.ndjson") - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_dev_tool_export_dashboard_by_id_to_folder(self): - """ - Test dev-tools/cmd/dashboards exports dashboard and removes unsupported characters - and separates each asset into a file under the appropriate folder - """ - - self.test_load_dashboard() - - folder_name = "my-system" + folder_name = "system-overview" path = os.path.normpath(self.beat_path + "/../dev-tools/cmd/dashboards/export_dashboards.go") command = path + " -kibana http://" + self.get_kibana_host() + ":" + self.get_kibana_port() command = "go run " + command + " -dashboard Metricbeat-system-overview -folder " + folder_name p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) content, err = p.communicate() - print(content, err) assert p.returncode == 0 - assert os.path.isfile("output.ndjson") is False - assert os.path.isdir(folder_name) is True - - kibana_semver = semver.VersionInfo.parse(self.get_version()) - assets_root = os.path.join(folder_name, "_meta", "kibana", str(kibana_semver.major)) - assert os.path.isdir(assets_root) is True - assert os.path.isdir(os.path.join(assets_root, "dashboard")) is True - assert os.path.isdir(os.path.join(assets_root, "visualization")) is True - - with open(os.path.join(assets_root, "dashboard", "Metricbeat-system-overview.json")) as dashboard_file: - dashboard = json.load(dashboard_file) - for reference in dashboard["references"]: - reference_path = os.path.join(assets_root, reference["type"], reference["id"]+".json") - assert os.path.isfile(reference_path) - - shutil.rmtree(folder_name) + self._check_if_dashboard_exported(folder_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -343,52 +222,28 @@ def test_dev_tool_export_dashboard_by_id_from_space(self): self.test_load_dashboard_into_space(False) + folder_name = "system-overview" path = os.path.normpath(self.beat_path + "/../dev-tools/cmd/dashboards/export_dashboards.go") command = path + " -kibana http://" + self.get_kibana_host() + ":" + self.get_kibana_port() - command = "go run " + command + " -dashboard Metricbeat-system-overview -space-id foo-bar" + command = "go run " + command + " -dashboard Metricbeat-system-overview -space-id foo-bar -folder " + folder_name p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) content, err = p.communicate() assert p.returncode == 0 - assert os.path.isfile("output.ndjson") is True - - with open('output.ndjson') as f: - content = f.read() - assert "Metricbeat-system-overview" in content - - os.remove("output.ndjson") - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_dev_tool_export_dashboard_from_yml(self): - """ - Test dev-tools/cmd/dashboards exports dashboard from dashboards YAML file - and removes unsupported characters - """ - - self.test_load_dashboard() - - path = os.path.normpath(self.beat_path + "/../dev-tools/cmd/dashboards/export_dashboards.go") - command = path + " -kibana http://" + self.get_kibana_host() + ":" + self.get_kibana_port() - command = "go run " + command + " -yml " + os.path.join(self.beat_path, "tests", "files", "dashboards.yml") - - p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - content, err = p.communicate() - - assert p.returncode == 0 + self._check_if_dashboard_exported(folder_name) - version = self.get_version() - kibana_semver = semver.VersionInfo.parse(version) - exported_dashboard_path = os.path.join(self.beat_path, "tests", "files", "_meta", - "kibana", str(kibana_semver.major), "dashboard", "Metricbeat-system-test-overview.ndjson") + def _check_if_dashboard_exported(self, folder_name): + kibana_semver = semver.VersionInfo.parse(self.get_version()) + dashboard_folder = os.path.join(folder_name, "_meta", "kibana", str(kibana_semver.major), "dashboard") + assert os.path.isdir(dashboard_folder) - with open(exported_dashboard_path) as f: + with open(os.path.join(dashboard_folder, "Metricbeat-system-overview.json")) as f: content = f.read() assert "Metricbeat-system-overview" in content - os.remove(exported_dashboard_path) + shutil.rmtree(folder_name) def get_host(self): return os.getenv('ES_HOST', 'localhost') + ':' + os.getenv('ES_PORT', '9200') From b66f29072c552e73c560e842ff162ee869216ec3 Mon Sep 17 00:00:00 2001 From: Andrea Spacca Date: Mon, 18 Oct 2021 12:04:03 +0200 Subject: [PATCH 4/7] Add deprecation warning for filebeat disabled modules (#28393) * Add deprecation warning for filebeat disabled modules --- filebeat/beater/filebeat.go | 23 ++++++ filebeat/fileset/modules.go | 78 +++++++++++++++----- filebeat/fileset/modules_integration_test.go | 6 +- filebeat/fileset/modules_test.go | 69 +++++++++++++---- 4 files changed, 140 insertions(+), 36 deletions(-) diff --git a/filebeat/beater/filebeat.go b/filebeat/beater/filebeat.go index 008bb36860b8..b80adc5c8483 100644 --- a/filebeat/beater/filebeat.go +++ b/filebeat/beater/filebeat.go @@ -116,6 +116,29 @@ func newBeater(b *beat.Beat, plugins PluginFactory, rawConfig *common.Config) (b } if !moduleRegistry.Empty() { logp.Info("Enabled modules/filesets: %s", moduleRegistry.InfoString()) + + // Deprecation warning logic for v8.0 (https://github.com/elastic/beats/pull/27526) + for _, mod := range moduleRegistry.ModuleNames() { + if mod == "" { + continue + } + + loadedFilesets, err := moduleRegistry.ModuleFilesets(mod) + if err != nil { + logp.Err("Error retrieving module filesets: %+v", err) + return nil, err + } + + configuredFilesets := moduleRegistry.ModuleConfiguredFilesets(mod) + if len(configuredFilesets) != len(loadedFilesets) { + for _, loadedFileset := range loadedFilesets { + if _, ok := configuredFilesets[loadedFileset]; !ok { + logp.Warn("Fileset `%s` for module `%s` is loaded but was not explicitly defined in the config. "+ + "Starting from v8.0 this fileset won't be loaded unless explicitly defined.", loadedFileset, mod) + } + } + } + } } moduleInputs, err := moduleRegistry.GetInputConfigs() diff --git a/filebeat/fileset/modules.go b/filebeat/fileset/modules.go index 69b49b013b6e..f3c94deefca6 100644 --- a/filebeat/fileset/modules.go +++ b/filebeat/fileset/modules.go @@ -44,19 +44,22 @@ var availableMLModules = map[string]string{ const logName = "modules" type ModuleRegistry struct { - registry map[string]map[string]*Fileset // module -> fileset -> Fileset - log *logp.Logger + configuredFilesets map[string]map[string]struct{} // module -> fileset -> struct{} + registry map[string]map[string]*Fileset // module -> fileset -> Fileset + log *logp.Logger } // newModuleRegistry reads and loads the configured module into the registry. func newModuleRegistry(modulesPath string, moduleConfigs []*ModuleConfig, overrides *ModuleOverrides, + configuredFilesets map[string]map[string]struct{}, beatInfo beat.Info, ) (*ModuleRegistry, error) { reg := ModuleRegistry{ - registry: map[string]map[string]*Fileset{}, - log: logp.NewLogger(logName), + configuredFilesets: configuredFilesets, + registry: map[string]map[string]*Fileset{}, + log: logp.NewLogger(logName), } for _, mcfg := range moduleConfigs { @@ -77,15 +80,23 @@ func newModuleRegistry(modulesPath string, } for _, filesetName := range moduleFilesets { + var hasOverride bool fcfg, exists := mcfg.Filesets[filesetName] if !exists { fcfg = &FilesetConfig{} } - fcfg, err = applyOverrides(fcfg, mcfg.Module, filesetName, overrides) + fcfg, hasOverride, err = applyOverrides(fcfg, mcfg.Module, filesetName, overrides) if err != nil { return nil, fmt.Errorf("error applying overrides on fileset %s/%s: %v", mcfg.Module, filesetName, err) } + if hasOverride { + if _, ok := reg.configuredFilesets[mcfg.Module]; !ok { + reg.configuredFilesets[mcfg.Module] = map[string]struct{}{} + } + + reg.configuredFilesets[mcfg.Module][filesetName] = struct{}{} + } if fcfg.Enabled != nil && !(*fcfg.Enabled) { continue @@ -141,16 +152,19 @@ func NewModuleRegistry(moduleConfigs []*common.Config, beatInfo beat.Info, init } } var mcfgs []*ModuleConfig + configuredFilesets := map[string]map[string]struct{}{} for _, cfg := range moduleConfigs { cfg, err = mergePathDefaults(cfg) if err != nil { return nil, err } - moduleConfig, err := mcfgFromConfig(cfg) + moduleConfig, moduleConfiguredFilests, err := mcfgFromConfig(cfg) if err != nil { return nil, errors.Wrap(err, "error unpacking module config") } + + configuredFilesets[moduleConfig.Module] = moduleConfiguredFilests mcfgs = append(mcfgs, moduleConfig) } @@ -159,22 +173,22 @@ func NewModuleRegistry(moduleConfigs []*common.Config, beatInfo beat.Info, init return nil, err } - return newModuleRegistry(modulesPath, mcfgs, modulesOverrides, beatInfo) + return newModuleRegistry(modulesPath, mcfgs, modulesOverrides, configuredFilesets, beatInfo) } -func mcfgFromConfig(cfg *common.Config) (*ModuleConfig, error) { +func mcfgFromConfig(cfg *common.Config) (*ModuleConfig, map[string]struct{}, error) { var mcfg ModuleConfig err := cfg.Unpack(&mcfg) if err != nil { - return nil, err + return nil, nil, err } var dict map[string]interface{} err = cfg.Unpack(&dict) if err != nil { - return nil, fmt.Errorf("error unpacking module %s in a dict: %v", mcfg.Module, err) + return nil, nil, fmt.Errorf("error unpacking module %s in a dict: %v", mcfg.Module, err) } mcfg.Filesets = map[string]*FilesetConfig{} @@ -185,17 +199,31 @@ func mcfgFromConfig(cfg *common.Config) (*ModuleConfig, error) { tmpCfg, err := common.NewConfigFrom(filesetConfig) if err != nil { - return nil, fmt.Errorf("error creating config from fileset %s/%s: %v", mcfg.Module, name, err) + return nil, nil, fmt.Errorf("error creating config from fileset %s/%s: %v", mcfg.Module, name, err) } fcfg, err := NewFilesetConfig(tmpCfg) if err != nil { - return nil, fmt.Errorf("error creating config from fileset %s/%s: %v", mcfg.Module, name, err) + return nil, nil, fmt.Errorf("error creating config from fileset %s/%s: %v", mcfg.Module, name, err) } mcfg.Filesets[name] = fcfg } - return &mcfg, nil + // This calls cfg.GetFields() instead of iterating over `dict` keys + // because cfg.Unpack above doesn't return keys that map to a nil value, + // but GetFields() returns all keys. We need to observe filesets that + // don't contain any configuration (all default values). + configuredFilets := map[string]struct{}{} + + for _, name := range cfg.GetFields() { + if name == "module" || name == "enabled" || name == "path" { + continue + } + + configuredFilets[name] = struct{}{} + } + + return &mcfg, configuredFilets, nil } func getCurrentModuleName(modulePath, module string) (string, bool) { @@ -239,20 +267,20 @@ func getModuleFilesets(modulePath, module string) ([]string, error) { func applyOverrides(fcfg *FilesetConfig, module, fileset string, - overrides *ModuleOverrides) (*FilesetConfig, error) { + overrides *ModuleOverrides) (*FilesetConfig, bool, error) { if overrides == nil { - return fcfg, nil + return fcfg, false, nil } overridesConfigs := overrides.Get(module, fileset) if len(overridesConfigs) == 0 { - return fcfg, nil + return fcfg, false, nil } config, err := common.NewConfigFrom(fcfg) if err != nil { - return nil, fmt.Errorf("error creating vars config object: %v", err) + return nil, false, fmt.Errorf("error creating vars config object: %v", err) } toMerge := []*common.Config{config} @@ -260,15 +288,15 @@ func applyOverrides(fcfg *FilesetConfig, resultConfig, err := common.MergeConfigs(toMerge...) if err != nil { - return nil, fmt.Errorf("error merging configs: %v", err) + return nil, false, fmt.Errorf("error merging configs: %v", err) } res, err := NewFilesetConfig(resultConfig) if err != nil { - return nil, fmt.Errorf("error unpacking configs: %v", err) + return nil, false, fmt.Errorf("error unpacking configs: %v", err) } - return res, nil + return res, true, nil } // appendWithoutDuplicates appends basic module configuration for each module in the @@ -485,3 +513,13 @@ func (reg *ModuleRegistry) ModuleFilesets(module string) ([]string, error) { modulesPath := paths.Resolve(paths.Home, "module") return getModuleFilesets(modulesPath, module) } + +// ModuleConfiguredFilesets return the map of configured filesets for the given module +// it returns an empty map if the module doesn't exist +func (reg *ModuleRegistry) ModuleConfiguredFilesets(module string) map[string]struct{} { + if _, ok := reg.configuredFilesets[module]; ok { + return reg.configuredFilesets[module] + } + + return map[string]struct{}{} +} diff --git a/filebeat/fileset/modules_integration_test.go b/filebeat/fileset/modules_integration_test.go index 63a145476522..a3bc364b606d 100644 --- a/filebeat/fileset/modules_integration_test.go +++ b/filebeat/fileset/modules_integration_test.go @@ -109,7 +109,7 @@ func TestSetupNginx(t *testing.T) { {Module: "nginx"}, } - reg, err := newModuleRegistry(modulesPath, configs, nil, makeTestInfo("5.2.0")) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, makeTestInfo("5.2.0")) if err != nil { t.Fatal(err) } @@ -188,7 +188,7 @@ func TestLoadMultiplePipelines(t *testing.T) { &ModuleConfig{"foo", &enabled, filesetConfigs}, } - reg, err := newModuleRegistry(modulesPath, configs, nil, makeTestInfo("6.6.0")) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, makeTestInfo("6.6.0")) if err != nil { t.Fatal(err) } @@ -233,7 +233,7 @@ func TestLoadMultiplePipelinesWithRollback(t *testing.T) { {"foo", &enabled, filesetConfigs}, } - reg, err := newModuleRegistry(modulesPath, configs, nil, makeTestInfo("6.6.0")) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, makeTestInfo("6.6.0")) if err != nil { t.Fatal(err) } diff --git a/filebeat/fileset/modules_test.go b/filebeat/fileset/modules_test.go index 0b842067e003..e8c1ae199cef 100644 --- a/filebeat/fileset/modules_test.go +++ b/filebeat/fileset/modules_test.go @@ -53,7 +53,7 @@ func TestNewModuleRegistry(t *testing.T) { {Module: "auditd"}, } - reg, err := newModuleRegistry(modulesPath, configs, nil, beat.Info{Version: "5.2.0"}) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, beat.Info{Version: "5.2.0"}) require.NoError(t, err) assert.NotNil(t, reg) @@ -118,7 +118,7 @@ func TestNewModuleRegistryConfig(t *testing.T) { }, } - reg, err := newModuleRegistry(modulesPath, configs, nil, beat.Info{Version: "5.2.0"}) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, beat.Info{Version: "5.2.0"}) require.NoError(t, err) assert.NotNil(t, reg) @@ -143,7 +143,7 @@ func TestMovedModule(t *testing.T) { }, } - reg, err := newModuleRegistry(modulesPath, configs, nil, beat.Info{Version: "5.2.0"}) + reg, err := newModuleRegistry(modulesPath, configs, nil, nil, beat.Info{Version: "5.2.0"}) require.NoError(t, err) assert.NotNil(t, reg) } @@ -158,7 +158,28 @@ func TestApplyOverrides(t *testing.T) { module, fileset string overrides *ModuleOverrides expected FilesetConfig + hasOverride bool }{ + { + name: "no overrides", + fcfg: FilesetConfig{ + Var: map[string]interface{}{ + "a": "test", + "b.c": "test", + }, + Input: map[string]interface{}{}, + }, + module: "nginx", + fileset: "access", + expected: FilesetConfig{ + Var: map[string]interface{}{ + "a": "test", + "b.c": "test", + }, + Input: map[string]interface{}{}, + }, + hasOverride: false, + }, { name: "var overrides", fcfg: FilesetConfig{ @@ -184,6 +205,7 @@ func TestApplyOverrides(t *testing.T) { }, Input: map[string]interface{}{}, }, + hasOverride: true, }, { name: "enable and var overrides", @@ -210,6 +232,7 @@ func TestApplyOverrides(t *testing.T) { }, Input: map[string]interface{}{}, }, + hasOverride: true, }, { name: "input overrides", @@ -229,14 +252,16 @@ func TestApplyOverrides(t *testing.T) { }, Var: map[string]interface{}{}, }, + hasOverride: true, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - result, err := applyOverrides(&test.fcfg, test.module, test.fileset, test.overrides) + result, hasOverride, err := applyOverrides(&test.fcfg, test.module, test.fileset, test.overrides) require.NoError(t, err) assert.Equal(t, &test.expected, result) + assert.Equal(t, test.hasOverride, hasOverride) }) } } @@ -336,17 +361,28 @@ func TestAppendWithoutDuplicates(t *testing.T) { func TestMcfgFromConfig(t *testing.T) { falseVar := false tests := []struct { - name string - config *common.Config - expected ModuleConfig + name string + config *common.Config + expectedModuleConfig ModuleConfig + expectedConfiguredFilesets map[string]struct{} }{ + { + name: "not defined fileset", + config: load(t, map[string]interface{}{ + "module": "nginx", + }), + expectedModuleConfig: ModuleConfig{ + Module: "nginx", + }, + expectedConfiguredFilesets: map[string]struct{}{}, + }, { name: "disable fileset", config: load(t, map[string]interface{}{ "module": "nginx", "error.enabled": false, }), - expected: ModuleConfig{ + expectedModuleConfig: ModuleConfig{ Module: "nginx", Filesets: map[string]*FilesetConfig{ "error": { @@ -356,6 +392,9 @@ func TestMcfgFromConfig(t *testing.T) { }, }, }, + expectedConfiguredFilesets: map[string]struct{}{ + "error": struct{}{}, + }, }, { name: "set variable", @@ -363,7 +402,7 @@ func TestMcfgFromConfig(t *testing.T) { "module": "nginx", "access.var.test": false, }), - expected: ModuleConfig{ + expectedModuleConfig: ModuleConfig{ Module: "nginx", Filesets: map[string]*FilesetConfig{ "access": { @@ -374,16 +413,20 @@ func TestMcfgFromConfig(t *testing.T) { }, }, }, + expectedConfiguredFilesets: map[string]struct{}{ + "access": struct{}{}, + }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - result, err := mcfgFromConfig(test.config) + result, configuredFilets, err := mcfgFromConfig(test.config) require.NoError(t, err) - assert.Equal(t, test.expected.Module, result.Module) - assert.Equal(t, len(test.expected.Filesets), len(result.Filesets)) - for name, fileset := range test.expected.Filesets { + assert.Equal(t, test.expectedConfiguredFilesets, configuredFilets) + assert.Equal(t, test.expectedModuleConfig.Module, result.Module) + assert.Equal(t, len(test.expectedModuleConfig.Filesets), len(result.Filesets)) + for name, fileset := range test.expectedModuleConfig.Filesets { assert.Equal(t, fileset, result.Filesets[name]) } }) From 7f1c76df7387f51056c96f88386efff23eb9c6f8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 12:15:06 +0200 Subject: [PATCH 5/7] chore(ci): remove not used param when triggering e2e tests (#27823) (#27828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 3bb268198463e3de570ac61ea55d95eaf49e58ae) Co-authored-by: Manuel de la Peña --- .ci/packaging.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/.ci/packaging.groovy b/.ci/packaging.groovy index c3db283d5e08..b6ca0def66da 100644 --- a/.ci/packaging.groovy +++ b/.ci/packaging.groovy @@ -426,7 +426,6 @@ def triggerE2ETests(String suite) { booleanParam(name: 'forceSkipPresubmit', value: true), booleanParam(name: 'notifyOnGreenBuilds', value: !isPR()), string(name: 'BEAT_VERSION', value: beatVersion), - booleanParam(name: 'BEATS_USE_CI_SNAPSHOTS', value: true), string(name: 'runTestsSuites', value: suite), string(name: 'GITHUB_CHECK_NAME', value: env.GITHUB_CHECK_E2E_TESTS_NAME), string(name: 'GITHUB_CHECK_REPO', value: env.REPO), From 1653da214fa744d1980973af9cd7f479ab92d030 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Mon, 18 Oct 2021 09:04:24 -0400 Subject: [PATCH 6/7] [Automation] Update elastic stack version to 7.16.0-8bf0b9b1 for testing (#28484) Co-authored-by: apmmachine Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- testing/environments/snapshot-oss.yml | 6 +++--- testing/environments/snapshot.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/environments/snapshot-oss.yml b/testing/environments/snapshot-oss.yml index 6eae40ed069a..7b6b2b8c9106 100644 --- a/testing/environments/snapshot-oss.yml +++ b/testing/environments/snapshot-oss.yml @@ -3,7 +3,7 @@ version: '2.3' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:9200/_cat/health?h=status | grep -q green"] retries: 300 @@ -17,7 +17,7 @@ services: - "indices.id_field_data.enabled=true" logstash: - image: docker.elastic.co/logstash/logstash-oss:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/logstash/logstash-oss:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9600/_node/stats"] retries: 600 @@ -27,7 +27,7 @@ services: - ./docker/logstash/pki:/etc/pki:ro kibana: - image: docker.elastic.co/kibana/kibana-oss:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/kibana/kibana-oss:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:5601/api/status?v8format=true | grep -q '\"overall\":{\"level\":\"available\"'"] retries: 600 diff --git a/testing/environments/snapshot.yml b/testing/environments/snapshot.yml index 0da8a5b5034b..9c62e788e596 100644 --- a/testing/environments/snapshot.yml +++ b/testing/environments/snapshot.yml @@ -3,7 +3,7 @@ version: '2.3' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:9200/_cat/health?h=status | grep -q green"] retries: 300 @@ -24,7 +24,7 @@ services: - "ingest.geoip.downloader.enabled=false" logstash: - image: docker.elastic.co/logstash/logstash:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/logstash/logstash:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9600/_node/stats"] retries: 600 @@ -34,7 +34,7 @@ services: - ./docker/logstash/pki:/etc/pki:ro kibana: - image: docker.elastic.co/kibana/kibana:7.16.0-86000c2d-SNAPSHOT + image: docker.elastic.co/kibana/kibana:7.16.0-8bf0b9b1-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:5601/api/status?v8format=true | grep -q '\"overall\":{\"level\":\"available\"'"] retries: 600 From 055e85955591c6a65ddda837c6e9baa587e09b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 18 Oct 2021 15:22:19 +0200 Subject: [PATCH 7/7] chore: use same branching schema for e2e (#28493) --- .ci/packaging.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/packaging.groovy b/.ci/packaging.groovy index b6ca0def66da..91853fa3a1ab 100644 --- a/.ci/packaging.groovy +++ b/.ci/packaging.groovy @@ -417,7 +417,7 @@ def runE2ETests(){ def triggerE2ETests(String suite) { echo("Triggering E2E tests for PR-${env.CHANGE_ID}. Test suites: ${suite}.") - def branchName = isPR() ? "${env.CHANGE_TARGET}" : "${env.JOB_BASE_NAME}.x" + def branchName = isPR() ? "${env.CHANGE_TARGET}" : "${env.JOB_BASE_NAME}" def e2eTestsPipeline = "e2e-tests/e2e-testing-mbp/${branchName}" def beatVersion = "${env.BEAT_VERSION}-SNAPSHOT"