diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index b3fa34b8b9b..3da2b9c4fcc 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -30,6 +30,7 @@ https://github.com/elastic/beats/compare/v7.5.0...v7.5.1[View commits]
- Fix docker network stats when multiple interfaces are configured. {issue}14586[14586] {pull}14825[14825]
- Fix ListMetrics pagination in aws module. {issue}14926[14926] {pull}14942[14942]
- Fix CPU count in docker/cpu in cases where no `online_cpus` are reported {pull}15070[15070]
+- Add domain state to kvm module {pull}17673[17673]
[[release-notes-7.5.0]]
=== Beats version 7.5.0
diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc
index b1f70eea949..a0e555166cc 100644
--- a/CHANGELOG.next.asciidoc
+++ b/CHANGELOG.next.asciidoc
@@ -77,6 +77,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Do not rotate log files on startup when interval is configured and rotateonstartup is disabled. {pull}17613[17613]
- Fix goroutine leak and Elasticsearch output file descriptor leak when output reloading is in use. {issue}10491[10491] {pull}17381[17381]
- Fix `setup.dashboards.index` setting not working. {pull}17749[17749]
+- Fix Elasticsearch license endpoint URL referenced in error message. {issue}17880[17880] {pull}18030[18030]
*Auditbeat*
@@ -199,6 +200,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Update RPM packages contained in Beat Docker images. {issue}17035[17035]
- Update supported versions of `redis` output. {pull}17198[17198]
- Update documentation for system.process.memory fields to include clarification on Windows os's. {pull}17268[17268]
+- Add `replace` processor for replacing string values of fields. {pull}17342[17342]
- Add optional regex based cid extractor to `add_kubernetes_metadata` processor. {pull}17360[17360]
- Add `urldecode` processor to for decoding URL-encoded fields. {pull}17505[17505]
- Add support for AWS IAM `role_arn` in credentials config. {pull}17658[17658] {issue}12464[12464]
diff --git a/Jenkinsfile b/Jenkinsfile
index ba73c431091..0ba1f3d8481 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -49,13 +49,13 @@ pipeline {
steps {
deleteDir()
gitCheckout(basedir: "${BASE_DIR}")
+ stash allowEmpty: true, name: 'source', useDefaultExcludes: false
dir("${BASE_DIR}"){
loadConfigEnvVars()
}
whenTrue(params.debug){
dumpFilteredEnvironment()
}
- stash allowEmpty: true, name: 'source', useDefaultExcludes: false
}
}
stage('Lint'){
@@ -606,6 +606,9 @@ pipeline {
always {
runbld()
}
+ cleanup {
+ notifyBuildResult(prComment: true)
+ }
}
}
@@ -867,7 +870,6 @@ def isChangedOSSCode(patterns) {
"^\\.ci/.*",
]
allPatterns.addAll(patterns)
- allPatterns.addAll(getVendorPatterns('libbeat'))
return isChanged(allPatterns)
}
@@ -882,7 +884,6 @@ def isChangedXPackCode(patterns) {
"^\\.ci/.*",
]
allPatterns.addAll(patterns)
- allPatterns.addAll(getVendorPatterns('x-pack/libbeat'))
return isChanged(allPatterns)
}
@@ -890,6 +891,10 @@ def loadConfigEnvVars(){
def empty = []
env.GO_VERSION = readFile(".go-version").trim()
+ withEnv(["HOME=${env.WORKSPACE}"]) {
+ sh(label: "Install Go ${env.GO_VERSION}", script: ".ci/scripts/install-go.sh")
+ }
+
// Libbeat is the core framework of Beats. It has no additional dependencies
// on other projects in the Beats repository.
env.BUILD_LIBBEAT = isChangedOSSCode(empty)
@@ -948,17 +953,25 @@ def loadConfigEnvVars(){
// involved.
env.BUILD_KUBERNETES = isChanged(["^deploy/kubernetes/.*"])
- env.BUILD_GENERATOR = isChangedOSSCode(getVendorPatterns('generator'))
+ def generatorPatterns = ['^generator/.*']
+ generatorPatterns.addAll(getVendorPatterns('generator/common/beatgen'))
+ generatorPatterns.addAll(getVendorPatterns('metricbeat/beater'))
+ env.BUILD_GENERATOR = isChangedOSSCode(generatorPatterns)
}
/**
This method grab the dependencies of a Go module and transform them on regexp
*/
def getVendorPatterns(beatName){
+ def os = goos()
+ def goRoot = "${env.WORKSPACE}/.gvm/versions/go${GO_VERSION}.${os}.amd64"
def output = ""
- docker.image("golang:${GO_VERSION}").inside{
+
+ withEnv([
+ "HOME=${env.WORKSPACE}/${env.BASE_DIR}",
+ "PATH=${env.WORKSPACE}/bin:${goRoot}/bin:${env.PATH}",
+ ]) {
output = sh(label: 'Get vendor dependency patterns', returnStdout: true, script: """
- export HOME=${WORKSPACE}/${BASE_DIR}
go list -mod=vendor -f '{{ .ImportPath }}{{ "\\n" }}{{ join .Deps "\\n" }}' ./${beatName}\
|awk '{print \$1"/.*"}'\
|sed -e "s#github.com/elastic/beats/v7/##g"
diff --git a/generator/_templates/metricbeat/{beat}/magefile.go b/generator/_templates/metricbeat/{beat}/magefile.go
index b1b78829ee1..934276e633b 100644
--- a/generator/_templates/metricbeat/{beat}/magefile.go
+++ b/generator/_templates/metricbeat/{beat}/magefile.go
@@ -16,6 +16,9 @@ import (
"github.com/elastic/beats/v7/dev-tools/mage/target/unittest"
"github.com/elastic/beats/v7/generator/common/beatgen"
metricbeat "github.com/elastic/beats/v7/metricbeat/scripts/mage"
+
+ // mage:import
+ _ "github.com/elastic/beats/v7/metricbeat/scripts/mage/target/metricset"
)
func init() {
diff --git a/libbeat/processors/actions/docs/replace.asciidoc b/libbeat/processors/actions/docs/replace.asciidoc
new file mode 100644
index 00000000000..3faf3e0bcce
--- /dev/null
+++ b/libbeat/processors/actions/docs/replace.asciidoc
@@ -0,0 +1,49 @@
+[[replace-fields]]
+=== Replace fields from events
+
+++++
+replace
+++++
+
+The `replace` processor takes a list of fields to replace the field value
+matching a pattern with replacement string. Under the `fields` key, each entry
+contains a `field: field-name`, `pattern: regex-pattern` and
+`replacement: replacement-string`, where:
+
+* `field` is the original field name
+* `pattern` is regex pattern to match field's value
+* `replacement` is the replacement string to use for updating the field's value
+
+The `replace` processor cannot be used to replace value with a completely new value.
+
+TIP: You can replace field value to truncate part of field value or replace
+it with a new string. It can also be used for masking PII information.
+
+Following example will change path from /usr/bin to /usr/local/bin
+
+[source,yaml]
+-------
+processors:
+- replace:
+ fields:
+ - field: "file.path"
+ pattern: "/usr/"
+ replacement: "/usr/local/"
+ ignore_missing: false
+ fail_on_error: true
+-------
+
+The `replace` processor has following configuration settings:
+
+`ignore_missing`:: (Optional) If set to true, no error is logged in case a specifiedfield
+is missing. Default is `false`.
+
+`fail_on_error`:: (Optional) If set to true, in case of an error the replacement of
+field values is stopped and the original event is returned. If set to false, replacement
+continues even if an error occurs during replacement. Default is `true`.
+
+See <> for a list of supported conditions.
+
+You can specify multiple `ignore_missing` processors under the `processors`
+section.
+
diff --git a/libbeat/processors/actions/replace.go b/libbeat/processors/actions/replace.go
new file mode 100644
index 00000000000..37245817050
--- /dev/null
+++ b/libbeat/processors/actions/replace.go
@@ -0,0 +1,118 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package actions
+
+import (
+ "fmt"
+ "regexp"
+
+ "github.com/pkg/errors"
+
+ "github.com/elastic/beats/v7/libbeat/beat"
+ "github.com/elastic/beats/v7/libbeat/common"
+ "github.com/elastic/beats/v7/libbeat/logp"
+ "github.com/elastic/beats/v7/libbeat/processors"
+ "github.com/elastic/beats/v7/libbeat/processors/checks"
+ jsprocessor "github.com/elastic/beats/v7/libbeat/processors/script/javascript/module/processor"
+)
+
+type replaceString struct {
+ config replaceStringConfig
+}
+
+type replaceStringConfig struct {
+ Fields []replaceConfig `config:"fields"`
+ IgnoreMissing bool `config:"ignore_missing"`
+ FailOnError bool `config:"fail_on_error"`
+}
+
+type replaceConfig struct {
+ Field string `config:"field"`
+ Pattern *regexp.Regexp `config:"pattern"`
+ Replacement string `config:"replacement"`
+}
+
+func init() {
+ processors.RegisterPlugin("replace",
+ checks.ConfigChecked(NewReplaceString,
+ checks.RequireFields("fields")))
+
+ jsprocessor.RegisterPlugin("Replace", NewReplaceString)
+}
+
+// NewReplaceString returns a new replace processor.
+func NewReplaceString(c *common.Config) (processors.Processor, error) {
+ config := replaceStringConfig{
+ IgnoreMissing: false,
+ FailOnError: true,
+ }
+ err := c.Unpack(&config)
+ if err != nil {
+ return nil, fmt.Errorf("failed to unpack the replace configuration: %s", err)
+ }
+
+ f := &replaceString{
+ config: config,
+ }
+ return f, nil
+}
+
+func (f *replaceString) Run(event *beat.Event) (*beat.Event, error) {
+ var backup common.MapStr
+ // Creates a copy of the event to revert in case of failure
+ if f.config.FailOnError {
+ backup = event.Fields.Clone()
+ }
+
+ for _, field := range f.config.Fields {
+ err := f.replaceField(field.Field, field.Pattern, field.Replacement, event.Fields)
+ if err != nil {
+ errMsg := fmt.Errorf("Failed to replace fields in processor: %s", err)
+ logp.Debug("replace", errMsg.Error())
+ if f.config.FailOnError {
+ event.Fields = backup
+ event.PutValue("error.message", errMsg.Error())
+ return event, err
+ }
+ }
+ }
+
+ return event, nil
+}
+
+func (f *replaceString) replaceField(field string, pattern *regexp.Regexp, replacement string, fields common.MapStr) error {
+ currentValue, err := fields.GetValue(field)
+ if err != nil {
+ // Ignore ErrKeyNotFound errors
+ if f.config.IgnoreMissing && errors.Cause(err) == common.ErrKeyNotFound {
+ return nil
+ }
+ return fmt.Errorf("could not fetch value for key: %s, Error: %s", field, err)
+ }
+
+ updatedString := pattern.ReplaceAllString(currentValue.(string), replacement)
+ _, err = fields.Put(field, updatedString)
+ if err != nil {
+ return fmt.Errorf("could not put value: %s: %v, %v", replacement, currentValue, err)
+ }
+ return nil
+}
+
+func (f *replaceString) String() string {
+ return "replace=" + fmt.Sprintf("%+v", f.config.Fields)
+}
diff --git a/libbeat/processors/actions/replace_test.go b/libbeat/processors/actions/replace_test.go
new file mode 100644
index 00000000000..e54d16c5012
--- /dev/null
+++ b/libbeat/processors/actions/replace_test.go
@@ -0,0 +1,248 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package actions
+
+import (
+ "reflect"
+ "regexp"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/elastic/beats/v7/libbeat/beat"
+ "github.com/elastic/beats/v7/libbeat/common"
+)
+
+func TestReplaceRun(t *testing.T) {
+ var tests = []struct {
+ description string
+ Fields []replaceConfig
+ IgnoreMissing bool
+ FailOnError bool
+ Input common.MapStr
+ Output common.MapStr
+ error bool
+ }{
+ {
+ description: "simple field replacing",
+ Fields: []replaceConfig{
+ {
+ Field: "f",
+ Pattern: regexp.MustCompile(`a`),
+ Replacement: "b",
+ },
+ },
+ Input: common.MapStr{
+ "f": "abc",
+ },
+ Output: common.MapStr{
+ "f": "bbc",
+ },
+ error: false,
+ IgnoreMissing: false,
+ FailOnError: true,
+ },
+ {
+ description: "Add one more hierarchy to event",
+ Fields: []replaceConfig{
+ {
+ Field: "f.b",
+ Pattern: regexp.MustCompile(`a`),
+ Replacement: "b",
+ },
+ },
+ Input: common.MapStr{
+ "f": common.MapStr{
+ "b": "abc",
+ },
+ },
+ Output: common.MapStr{
+ "f": common.MapStr{
+ "b": "bbc",
+ },
+ },
+ error: false,
+ IgnoreMissing: false,
+ FailOnError: true,
+ },
+ {
+ description: "replace two fields at the same time.",
+ Fields: []replaceConfig{
+ {
+ Field: "f",
+ Pattern: regexp.MustCompile(`a.*c`),
+ Replacement: "cab",
+ },
+ {
+ Field: "g",
+ Pattern: regexp.MustCompile(`ef`),
+ Replacement: "oor",
+ },
+ },
+ Input: common.MapStr{
+ "f": "abbbc",
+ "g": "def",
+ },
+ Output: common.MapStr{
+ "f": "cab",
+ "g": "door",
+ },
+ error: false,
+ IgnoreMissing: false,
+ FailOnError: true,
+ },
+ {
+ description: "test missing fields",
+ Fields: []replaceConfig{
+ {
+ Field: "f",
+ Pattern: regexp.MustCompile(`abc`),
+ Replacement: "xyz",
+ },
+ {
+ Field: "g",
+ Pattern: regexp.MustCompile(`def`),
+ Replacement: "",
+ },
+ },
+ Input: common.MapStr{
+ "m": "abc",
+ "n": "def",
+ },
+ Output: common.MapStr{
+ "m": "abc",
+ "n": "def",
+ "error": common.MapStr{
+ "message": "Failed to replace fields in processor: could not fetch value for key: f, Error: key not found",
+ },
+ },
+ error: true,
+ IgnoreMissing: false,
+ FailOnError: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.description, func(t *testing.T) {
+ f := &replaceString{
+ config: replaceStringConfig{
+ Fields: test.Fields,
+ IgnoreMissing: test.IgnoreMissing,
+ FailOnError: test.FailOnError,
+ },
+ }
+ event := &beat.Event{
+ Fields: test.Input,
+ }
+
+ newEvent, err := f.Run(event)
+ if !test.error {
+ assert.Nil(t, err)
+ } else {
+ assert.NotNil(t, err)
+ }
+
+ assert.True(t, reflect.DeepEqual(newEvent.Fields, test.Output))
+ })
+ }
+}
+
+func TestReplaceField(t *testing.T) {
+ var tests = []struct {
+ Field string
+ Pattern *regexp.Regexp
+ Replacement string
+ ignoreMissing bool
+ failOnError bool
+ Input common.MapStr
+ Output common.MapStr
+ error bool
+ description string
+ }{
+ {
+ description: "replace part of field value with another string",
+ Field: "f",
+ Pattern: regexp.MustCompile(`a`),
+ Replacement: "b",
+ Input: common.MapStr{
+ "f": "abc",
+ },
+ Output: common.MapStr{
+ "f": "bbc",
+ },
+ error: false,
+ failOnError: true,
+ ignoreMissing: false,
+ },
+ {
+ description: "Add hierarchy to event and replace",
+ Field: "f.b",
+ Pattern: regexp.MustCompile(`a`),
+ Replacement: "b",
+ Input: common.MapStr{
+ "f": common.MapStr{
+ "b": "abc",
+ },
+ },
+ Output: common.MapStr{
+ "f": common.MapStr{
+ "b": "bbc",
+ },
+ },
+ error: false,
+ ignoreMissing: false,
+ failOnError: true,
+ },
+ {
+ description: "try replacing value of missing fields in event",
+ Field: "f",
+ Pattern: regexp.MustCompile(`abc`),
+ Replacement: "xyz",
+ Input: common.MapStr{
+ "m": "abc",
+ "n": "def",
+ },
+ Output: common.MapStr{
+ "m": "abc",
+ "n": "def",
+ },
+ error: true,
+ ignoreMissing: false,
+ failOnError: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.description, func(t *testing.T) {
+
+ f := &replaceString{
+ config: replaceStringConfig{
+ IgnoreMissing: test.ignoreMissing,
+ FailOnError: test.failOnError,
+ },
+ }
+
+ err := f.replaceField(test.Field, test.Pattern, test.Replacement, test.Input)
+ if err != nil {
+ assert.Equal(t, test.error, true)
+ }
+
+ assert.True(t, reflect.DeepEqual(test.Input, test.Output))
+ })
+ }
+}
diff --git a/metricbeat/Makefile b/metricbeat/Makefile
index 9cbf88c3a59..7a05a566775 100644
--- a/metricbeat/Makefile
+++ b/metricbeat/Makefile
@@ -3,6 +3,6 @@ ES_BEATS ?= ..
include $(ES_BEATS)/dev-tools/make/mage.mk
# Creates a new metricset. Requires the params MODULE and METRICSET
-.PHONY: create-metricset
+.PHONY: create-metricset
create-metricset:
mage createMetricset
diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc
index 04c431efd59..0aaafa9488b 100644
--- a/metricbeat/docs/fields.asciidoc
+++ b/metricbeat/docs/fields.asciidoc
@@ -25865,6 +25865,50 @@ type: long
Domain name
+type: keyword
+
+--
+
+[float]
+=== status
+
+status
+
+
+
+[float]
+=== stat
+
+Memory stat
+
+
+
+*`kvm.status.stat.state`*::
++
+--
+domain state
+
+
+type: keyword
+
+--
+
+*`kvm.status.id`*::
++
+--
+Domain id
+
+
+type: long
+
+--
+
+*`kvm.status.name`*::
++
+--
+Domain name
+
+
type: keyword
--
diff --git a/metricbeat/docs/modules/kvm.asciidoc b/metricbeat/docs/modules/kvm.asciidoc
index f8373184ba1..bc29173f280 100644
--- a/metricbeat/docs/modules/kvm.asciidoc
+++ b/metricbeat/docs/modules/kvm.asciidoc
@@ -20,7 +20,7 @@ in <>. Here is an example configuration:
----
metricbeat.modules:
- module: kvm
- metricsets: ["dommemstat"]
+ metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
@@ -39,5 +39,9 @@ The following metricsets are available:
* <>
+* <>
+
include::kvm/dommemstat.asciidoc[]
+include::kvm/status.asciidoc[]
+
diff --git a/metricbeat/docs/modules/kvm/status.asciidoc b/metricbeat/docs/modules/kvm/status.asciidoc
new file mode 100644
index 00000000000..5fea3653349
--- /dev/null
+++ b/metricbeat/docs/modules/kvm/status.asciidoc
@@ -0,0 +1,24 @@
+////
+This file is generated! See scripts/mage/docs_collector.go
+////
+
+[[metricbeat-metricset-kvm-status]]
+=== kvm status metricset
+
+beta[]
+
+include::../../../module/kvm/status/_meta/docs.asciidoc[]
+
+This is a default metricset. If the host module is unconfigured, this metricset is enabled by default.
+
+==== Fields
+
+For a description of each field in the metricset, see the
+<> section.
+
+Here is an example document generated by this metricset:
+
+[source,json]
+----
+include::../../../module/kvm/status/_meta/data.json[]
+----
diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc
index fe03abd62a3..bacbcb00906 100644
--- a/metricbeat/docs/modules_list.asciidoc
+++ b/metricbeat/docs/modules_list.asciidoc
@@ -168,7 +168,8 @@ This file is generated! See scripts/mage/docs_collector.go
|<>
|<>
|<> beta[] |image:./images/icon-no.png[No prebuilt dashboards] |
-.1+| .1+| |<> beta[]
+.2+| .2+| |<> beta[]
+|<> beta[]
|<> |image:./images/icon-no.png[No prebuilt dashboards] |
.2+| .2+| |<>
|<>
diff --git a/metricbeat/include/list_common.go b/metricbeat/include/list_common.go
index f15d6a4be16..ced01fa0d57 100644
--- a/metricbeat/include/list_common.go
+++ b/metricbeat/include/list_common.go
@@ -92,6 +92,7 @@ import (
_ "github.com/elastic/beats/v7/metricbeat/module/kibana/status"
_ "github.com/elastic/beats/v7/metricbeat/module/kvm"
_ "github.com/elastic/beats/v7/metricbeat/module/kvm/dommemstat"
+ _ "github.com/elastic/beats/v7/metricbeat/module/kvm/status"
_ "github.com/elastic/beats/v7/metricbeat/module/logstash"
_ "github.com/elastic/beats/v7/metricbeat/module/logstash/node"
_ "github.com/elastic/beats/v7/metricbeat/module/logstash/node_stats"
diff --git a/metricbeat/magefile.go b/metricbeat/magefile.go
index 0281c6892ba..b46dc9c7957 100644
--- a/metricbeat/magefile.go
+++ b/metricbeat/magefile.go
@@ -27,7 +27,6 @@ import (
"time"
"github.com/magefile/mage/mg"
- "github.com/magefile/mage/sh"
devtools "github.com/elastic/beats/v7/dev-tools/mage"
metricbeat "github.com/elastic/beats/v7/metricbeat/scripts/mage"
@@ -48,6 +47,8 @@ import (
"github.com/elastic/beats/v7/dev-tools/mage/target/unittest"
// mage:import
_ "github.com/elastic/beats/v7/dev-tools/mage/target/compose"
+ // mage:import
+ _ "github.com/elastic/beats/v7/metricbeat/scripts/mage/target/metricset"
)
func init() {
@@ -197,29 +198,3 @@ func PythonIntegTest(ctx context.Context) error {
return devtools.PythonNoseTest(devtools.DefaultPythonTestIntegrationArgs())
}, devtools.ListMatchingEnvVars("NOSE_")...)
}
-
-// CreateMetricset creates a new metricset.
-//
-// Required ENV variables:
-// * MODULE: Name of the module
-// * METRICSET: Name of the metricset
-func CreateMetricset(ctx context.Context) error {
- ve, err := devtools.PythonVirtualenv()
- if err != nil {
- return err
- }
- python, err := devtools.LookVirtualenvPath(ve, "python")
- if err != nil {
- return err
- }
- path, err := os.Getwd()
- if err != nil {
- return err
- }
-
- _, err = sh.Exec(
- map[string]string{}, os.Stdout, os.Stderr, python, "scripts/create_metricset.py",
- "--path", path, "--module", os.Getenv("MODULE"), "--metricset", os.Getenv("METRICSET"),
- )
- return err
-}
diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml
index 6de1e04436a..bdbb3ae87ba 100644
--- a/metricbeat/metricbeat.reference.yml
+++ b/metricbeat/metricbeat.reference.yml
@@ -556,7 +556,7 @@ metricbeat.modules:
#--------------------------------- Kvm Module ---------------------------------
- module: kvm
- metricsets: ["dommemstat"]
+ metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
diff --git a/metricbeat/module/kvm/_meta/config.reference.yml b/metricbeat/module/kvm/_meta/config.reference.yml
index 79f754a52cb..84e584787e1 100644
--- a/metricbeat/module/kvm/_meta/config.reference.yml
+++ b/metricbeat/module/kvm/_meta/config.reference.yml
@@ -1,5 +1,5 @@
- module: kvm
- metricsets: ["dommemstat"]
+ metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
diff --git a/metricbeat/module/kvm/_meta/config.yml b/metricbeat/module/kvm/_meta/config.yml
index 2df123ca14d..78509f63aa4 100644
--- a/metricbeat/module/kvm/_meta/config.yml
+++ b/metricbeat/module/kvm/_meta/config.yml
@@ -1,5 +1,6 @@
- module: kvm
#metricsets:
# - dommemstat
+ # - status
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
diff --git a/metricbeat/module/kvm/fields.go b/metricbeat/module/kvm/fields.go
index 456017804b4..4f509af839a 100644
--- a/metricbeat/module/kvm/fields.go
+++ b/metricbeat/module/kvm/fields.go
@@ -32,5 +32,5 @@ func init() {
// AssetKvm returns asset data.
// This is the base64 encoded gzipped contents of module/kvm.
func AssetKvm() string {
- return "eJyskDFuwzAMRXed4iN7LqChU9ceQq3YQLBoGrLsQrcvnEZFotByh3Lw4G+//8gzBioWw8oGyCFHsjgNK58MkCiSm8ninbIzgKf5I4UpBxktXgyA7T+w+CWSAT4DRT/ba3DG6JgqeJtcJrK4JFmm2xuF9wi5B3lhJp6zy7+Rxtzl3iKN0u5Zp1V5FGogPaFDrZ95I5ZUdLDucu+zPZW4Og1UviR59YtDs8Zur6uqrC4uPZco4+V/RLSmahGel+3UH1a/CrswPlO79+/f/q+dV/R3AAAA///hct15"
+ return "eJzckzFuxCAQRXtO8bX9XoAiVdocgoTJCpkxFmBHvn3k7BLZeBZHStLsFC485v0HZs7oaNboJlZAdtmTxqmb+KSASJ5MIo1XykYBltJbdEN2odd4UgCWdeBgR08KeHfkbdJfjTN6w1TAS+V5II1LDONweyPwtpA1yAZm4pRN/m5JzLvcW0ui1PssVatshSpIS+hQ61ovxCHOMlh2WfssT6FdnDqaP0K04heHZpXdvayiMhk/tlx86C9/IyIlFQu332wj/jD6ObBx/Z7aPP/22f80c4Ne378x/WYYdoTHGIRl2b9Ogr3+FSnnQe/eZwAAAP//6Q5sWg=="
}
diff --git a/metricbeat/module/kvm/status/_meta/data.json b/metricbeat/module/kvm/status/_meta/data.json
new file mode 100644
index 00000000000..fb7fd3c3595
--- /dev/null
+++ b/metricbeat/module/kvm/status/_meta/data.json
@@ -0,0 +1,28 @@
+{
+ "@timestamp": "2017-10-12T08:05:34.853Z",
+ "agent": {
+ "hostname": "host.example.com",
+ "name": "host.example.com"
+ },
+ "event":{
+ "dataset":"kvm.status",
+ "module":"kvm",
+ "duration":4012216
+ },
+ "metricset":{
+ "name":"status"
+ },
+ "service":{
+ "address":"unix:///var/run/libvirt/libvirt-sock",
+ "type":"kvm"
+ },
+ "kvm":{
+ "status":{
+ "stat":{
+ "state":"running"
+ },
+ "id":1,
+ "name":"generic-2"
+ }
+ }
+}
diff --git a/metricbeat/module/kvm/status/_meta/docs.asciidoc b/metricbeat/module/kvm/status/_meta/docs.asciidoc
new file mode 100644
index 00000000000..b94f0f0f147
--- /dev/null
+++ b/metricbeat/module/kvm/status/_meta/docs.asciidoc
@@ -0,0 +1 @@
+This is the status metricset of the module kvm.
diff --git a/metricbeat/module/kvm/status/_meta/fields.yml b/metricbeat/module/kvm/status/_meta/fields.yml
new file mode 100644
index 00000000000..9f75085f2cf
--- /dev/null
+++ b/metricbeat/module/kvm/status/_meta/fields.yml
@@ -0,0 +1,23 @@
+- name: status
+ type: group
+ description: >
+ status
+ release: beta
+ fields:
+ - name: stat
+ type: group
+ description: >
+ Memory stat
+ fields:
+ - name: state
+ type: keyword
+ description: >
+ domain state
+ - name: id
+ type: long
+ description: >
+ Domain id
+ - name: name
+ type: keyword
+ description: >
+ Domain name
diff --git a/metricbeat/module/kvm/status/status.go b/metricbeat/module/kvm/status/status.go
new file mode 100644
index 00000000000..eab1b947d7f
--- /dev/null
+++ b/metricbeat/module/kvm/status/status.go
@@ -0,0 +1,161 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package status
+
+import (
+ "net"
+ "net/url"
+ "time"
+
+ "github.com/pkg/errors"
+
+ "github.com/digitalocean/go-libvirt"
+ "github.com/digitalocean/go-libvirt/libvirttest"
+
+ "github.com/elastic/beats/v7/libbeat/common"
+ "github.com/elastic/beats/v7/libbeat/common/cfgwarn"
+ "github.com/elastic/beats/v7/metricbeat/mb"
+)
+
+// init registers the MetricSet with the central registry as soon as the program
+// starts. The New function will be called later to instantiate an instance of
+// the MetricSet for each host defined in the module's configuration. After the
+// MetricSet has been created then Fetch will begin to be called periodically.
+func init() {
+ mb.Registry.MustAddMetricSet("kvm", "status", New,
+ mb.DefaultMetricSet(),
+ )
+}
+
+// MetricSet holds any configuration or state information. It must implement
+// the mb.MetricSet interface. And this is best achieved by embedding
+// mb.BaseMetricSet because it implements all of the required mb.MetricSet
+// interface methods except for Fetch.
+type MetricSet struct {
+ mb.BaseMetricSet
+ Timeout time.Duration
+ HostURL *url.URL
+}
+
+// New creates a new instance of the MetricSet. New is responsible for unpacking
+// any MetricSet specific configuration options if there are any.
+func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
+ cfgwarn.Beta("The kvm status metricset is beta.")
+ u, err := url.Parse(base.HostData().URI)
+ if err != nil {
+ return nil, err
+ }
+
+ return &MetricSet{
+ BaseMetricSet: base,
+ Timeout: base.Module().Config().Timeout,
+ HostURL: u,
+ }, nil
+}
+
+// Fetch methods implements the data gathering and data conversion to the right
+// format. It publishes the event which is then forwarded to the output. In case
+// of an error set the Error field of mb.Event or simply call report.Error().
+func (m *MetricSet) Fetch(report mb.ReporterV2) error {
+ var (
+ c net.Conn
+ err error
+ )
+
+ u := m.HostURL
+
+ if u.Scheme == "test" {
+ // when running tests, a mock Libvirt server is used
+ c = libvirttest.New()
+ } else {
+ address := u.Host
+ if u.Host == "" {
+ address = u.Path
+ }
+
+ c, err = net.DialTimeout(u.Scheme, address, m.Timeout)
+ if err != nil {
+ return errors.Wrapf(err, "cannot connect to %v", u)
+ }
+ }
+
+ defer c.Close()
+
+ l := libvirt.New(c)
+ if err = l.Connect(); err != nil {
+ return errors.Wrap(err, "error connecting to libvirtd")
+ }
+ defer func() {
+ if err = l.Disconnect(); err != nil {
+ msg := errors.Wrap(err, "failed to disconnect")
+ report.Error(msg)
+ m.Logger().Error(msg)
+ }
+ }()
+
+ domains, err := l.Domains()
+ if err != nil {
+ return errors.Wrap(err, "error listing domains")
+ }
+
+ for _, d := range domains {
+ state, err := l.DomainState(d.Name)
+ if err != nil {
+ continue
+ }
+ reported := report.Event(mb.Event{
+ ModuleFields: common.MapStr{
+ "id": d.ID,
+ "name": d.Name,
+ },
+ MetricSetFields: common.MapStr{
+ "stat": common.MapStr{
+ "state": getDomainStateName(state),
+ },
+ },
+ })
+ if !reported {
+ return nil
+ }
+ }
+
+ return nil
+}
+
+func getDomainStateName(tag libvirt.DomainState) string {
+ switch tag {
+ case 0:
+ return "no state"
+ case 1:
+ return "running"
+ case 2:
+ return "blocked"
+ case 3:
+ return "paused"
+ case 4:
+ return "shutdown"
+ case 5:
+ return "shutoff"
+ case 6:
+ return "crashed"
+ case 7:
+ return "suspended"
+ default:
+ return "unidentified"
+ }
+}
diff --git a/metricbeat/module/kvm/status/status_test.go b/metricbeat/module/kvm/status/status_test.go
new file mode 100644
index 00000000000..e484cd775be
--- /dev/null
+++ b/metricbeat/module/kvm/status/status_test.go
@@ -0,0 +1,69 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package status
+
+import (
+ "testing"
+
+ "github.com/digitalocean/go-libvirt/libvirttest"
+ "github.com/stretchr/testify/assert"
+
+ mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing"
+)
+
+func TestFetchEventContents(t *testing.T) {
+ conn := libvirttest.New()
+
+ f := mbtest.NewReportingMetricSetV2Error(t, getConfig(conn))
+
+ events, errs := mbtest.ReportingFetchV2Error(f)
+ if len(errs) > 0 {
+ t.Fatal(errs)
+ }
+ if len(events) == 0 {
+ t.Fatal("no events received")
+ }
+
+ for _, e := range events {
+ if e.Error != nil {
+ t.Fatalf("received error: %+v", e.Error)
+ }
+ }
+ if len(events) == 0 {
+ t.Fatal("received no events")
+ }
+
+ e := events[0]
+
+ t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), e)
+
+ statName, err := e.MetricSetFields.GetValue("stat.state")
+ if err == nil {
+ assert.EqualValues(t, statName.(string), "running")
+ } else {
+ t.Errorf("error while getting value from event: %v", err)
+ }
+}
+
+func getConfig(conn *libvirttest.MockLibvirt) map[string]interface{} {
+ return map[string]interface{}{
+ "module": "kvm",
+ "metricsets": []string{"status"},
+ "hosts": []string{"test://" + conn.RemoteAddr().String() + ":123"},
+ }
+}
diff --git a/metricbeat/modules.d/kvm.yml.disabled b/metricbeat/modules.d/kvm.yml.disabled
index 878e279b969..8450e1afc6d 100644
--- a/metricbeat/modules.d/kvm.yml.disabled
+++ b/metricbeat/modules.d/kvm.yml.disabled
@@ -4,5 +4,6 @@
- module: kvm
#metricsets:
# - dommemstat
+ # - status
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
diff --git a/metricbeat/scripts/mage/target/metricset/metricset.go b/metricbeat/scripts/mage/target/metricset/metricset.go
new file mode 100644
index 00000000000..b1899e9352a
--- /dev/null
+++ b/metricbeat/scripts/mage/target/metricset/metricset.go
@@ -0,0 +1,54 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package metricset
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/magefile/mage/sh"
+
+ devtools "github.com/elastic/beats/v7/dev-tools/mage"
+)
+
+// CreateMetricset creates a new metricset.
+//
+// Required ENV variables:
+// * MODULE: Name of the module
+// * METRICSET: Name of the metricset
+func CreateMetricset() error {
+ ve, err := devtools.PythonVirtualenv()
+ if err != nil {
+ return err
+ }
+ python, err := devtools.LookVirtualenvPath(ve, "python")
+ if err != nil {
+ return err
+ }
+ beatsDir, err := devtools.ElasticBeatsDir()
+ if err != nil {
+ return err
+ }
+ scriptPath := filepath.Join(beatsDir, "metricbeat", "scripts", "create_metricset.py")
+
+ _, err = sh.Exec(
+ map[string]string{}, os.Stdout, os.Stderr, python, scriptPath,
+ "--path", devtools.CWD(), "--module", os.Getenv("MODULE"), "--metricset", os.Getenv("METRICSET"),
+ )
+ return err
+}
diff --git a/x-pack/elastic-agent/CHANGELOG.asciidoc b/x-pack/elastic-agent/CHANGELOG.asciidoc
index 9cdaa81432c..ed928e1d688 100644
--- a/x-pack/elastic-agent/CHANGELOG.asciidoc
+++ b/x-pack/elastic-agent/CHANGELOG.asciidoc
@@ -38,4 +38,5 @@
- Expose stream.* variables in events {pull}17468[17468]
- Monitoring configuration reloadable {pull}17855[17855]
- Pack ECS metadata to request payload send to fleet {pull}17894[17894]
+- Allow CLI overrides of paths {pull}17781[17781]
- Enable Filebeat input: S3, Azureeventhub, cloudfoundry, httpjson, netflow, o365audit. {pull}17909[17909]
diff --git a/x-pack/elastic-agent/main_test.go b/x-pack/elastic-agent/main_test.go
index cdced7ea677..79e2a9dc719 100644
--- a/x-pack/elastic-agent/main_test.go
+++ b/x-pack/elastic-agent/main_test.go
@@ -8,17 +8,21 @@ import (
"flag"
"testing"
- // Just using this a place holder.
- "github.com/elastic/beats/v7/x-pack/filebeat/cmd"
+ "github.com/spf13/cobra"
)
var systemTest *bool
func init() {
testing.Init()
+
+ cmd := &cobra.Command{
+ Use: "elastic-agent [subcommand]",
+ }
+
systemTest = flag.Bool("systemTest", false, "Set to true when running system tests")
- cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("systemTest"))
- cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("test.coverprofile"))
+ cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("systemTest"))
+ cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("test.coverprofile"))
}
// Test started when the test binary is started. Only calls main.
diff --git a/x-pack/elastic-agent/pkg/agent/application/global_config.go b/x-pack/elastic-agent/pkg/agent/application/global_config.go
index 44e9f2772ff..a08a59b0912 100644
--- a/x-pack/elastic-agent/pkg/agent/application/global_config.go
+++ b/x-pack/elastic-agent/pkg/agent/application/global_config.go
@@ -8,33 +8,64 @@ import (
"os"
"path/filepath"
+ "github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config"
)
var (
- homePath string
- dataPath string
+ homePath string
+ dataPath string
+ overwrites *common.Config
)
func init() {
homePath = retrieveExecutablePath()
dataPath = retrieveDataPath()
+ overwrites = common.NewConfig()
+ common.ConfigOverwriteFlag(nil, overwrites, "path.home", "path.home", "", "Agent root path")
+ common.ConfigOverwriteFlag(nil, overwrites, "path.data", "path.data", "", "Data path contains Agent managed binaries")
+}
+
+// HomePath returns home path where.
+func HomePath() string {
+ if val, err := overwrites.String("path.home", -1); err == nil {
+ return val
+ }
+
+ return homePath
+}
+
+// DataPath returns data path where.
+func DataPath() string {
+ if val, err := overwrites.String("path.data", -1); err == nil {
+ return val
+ }
+
+ return dataPath
}
// InjectAgentConfig injects config to a provided configuration.
func InjectAgentConfig(c *config.Config) error {
- globalConfig := AgentGlobalConfig()
+ globalConfig := agentGlobalConfig()
if err := c.Merge(globalConfig); err != nil {
return errors.New("failed to inject agent global config", err, errors.TypeConfig)
}
+ return injectOverwrites(c)
+}
+
+func injectOverwrites(c *config.Config) error {
+ if err := c.Merge(overwrites); err != nil {
+ return errors.New("failed to inject agent overwrites", err, errors.TypeConfig)
+ }
+
return nil
}
-// AgentGlobalConfig gets global config used for resolution of variables inside configuration
+// agentGlobalConfig gets global config used for resolution of variables inside configuration
// such as ${path.data}.
-func AgentGlobalConfig() map[string]interface{} {
+func agentGlobalConfig() map[string]interface{} {
return map[string]interface{}{
"path": map[string]interface{}{
"data": dataPath,
diff --git a/x-pack/elastic-agent/pkg/agent/cmd/common.go b/x-pack/elastic-agent/pkg/agent/cmd/common.go
index 0189f8e408d..956b7324d3c 100644
--- a/x-pack/elastic-agent/pkg/agent/cmd/common.go
+++ b/x-pack/elastic-agent/pkg/agent/cmd/common.go
@@ -5,30 +5,30 @@
package cmd
import (
+ "flag"
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
+ "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/basecmd"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli"
)
-var defaultConfig = "elastic-agent.yml"
+const defaultConfig = "elastic-agent.yml"
type globalFlags struct {
- PathConfigFile string
PathConfig string
- PathData string
- PathHome string
- PathLogs string
+ PathConfigFile string
FlagStrictPerms bool
}
+// Config returns path which identifies configuration file.
func (f *globalFlags) Config() string {
if len(f.PathConfigFile) == 0 {
- return filepath.Join(f.PathHome, defaultConfig)
+ return filepath.Join(application.HomePath(), defaultConfig)
}
return f.PathConfigFile
}
@@ -50,11 +50,11 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command {
flags := &globalFlags{}
+ cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.home"))
+ cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.data"))
+
cmd.PersistentFlags().StringVarP(&flags.PathConfigFile, "", "c", defaultConfig, fmt.Sprintf(`Configuration file, relative to path.config (default "%s")`, defaultConfig))
- cmd.PersistentFlags().StringVarP(&flags.PathHome, "path.home", "", "", "Home path")
cmd.PersistentFlags().StringVarP(&flags.PathConfig, "path.config", "", "${path.home}", "Configuration path")
- cmd.PersistentFlags().StringVarP(&flags.PathData, "path.data", "", "${path.home}/data", "Data path")
- cmd.PersistentFlags().StringVarP(&flags.PathLogs, "path.logs", "", "${path.home}/logs", "Logs path")
cmd.PersistentFlags().BoolVarP(&flags.FlagStrictPerms, "strict.perms", "", true, "Strict permission checking on config files")
// Add version.
diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go
index a2a7ee48d22..abc5efb3b90 100644
--- a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go
+++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go
@@ -46,13 +46,13 @@ func newEnrollCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStr
func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error {
warn.PrintNotGA(streams.Out)
-
- config, err := config.LoadYAML(flags.PathConfigFile)
+ pathConfigFile := flags.Config()
+ config, err := config.LoadYAML(pathConfigFile)
if err != nil {
return errors.New(err,
- fmt.Sprintf("could not read configuration file %s", flags.PathConfigFile),
+ fmt.Sprintf("could not read configuration file %s", pathConfigFile),
errors.TypeFilesystem,
- errors.M(errors.MetaKeyPath, flags.PathConfigFile))
+ errors.M(errors.MetaKeyPath, pathConfigFile))
}
force, _ := cmd.Flags().GetBool("force")
@@ -95,7 +95,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args
c, err := application.NewEnrollCmd(
logger,
&options,
- flags.PathConfigFile,
+ pathConfigFile,
)
if err != nil {
diff --git a/x-pack/elastic-agent/pkg/agent/cmd/run.go b/x-pack/elastic-agent/pkg/agent/cmd/run.go
index f0196ba7875..db199e2b47d 100644
--- a/x-pack/elastic-agent/pkg/agent/cmd/run.go
+++ b/x-pack/elastic-agent/pkg/agent/cmd/run.go
@@ -33,12 +33,13 @@ func newRunCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStream
}
func run(flags *globalFlags, streams *cli.IOStreams) error {
- config, err := config.LoadYAML(flags.PathConfigFile)
+ pathConfigFile := flags.Config()
+ config, err := config.LoadYAML(pathConfigFile)
if err != nil {
return errors.New(err,
- fmt.Sprintf("could not read configuration file %s", flags.PathConfigFile),
+ fmt.Sprintf("could not read configuration file %s", pathConfigFile),
errors.TypeFilesystem,
- errors.M(errors.MetaKeyPath, flags.PathConfigFile))
+ errors.M(errors.MetaKeyPath, pathConfigFile))
}
logger, err := logger.NewFromConfig(config)
@@ -46,7 +47,7 @@ func run(flags *globalFlags, streams *cli.IOStreams) error {
return err
}
- app, err := application.New(logger, flags.PathConfigFile)
+ app, err := application.New(logger, pathConfigFile)
if err != nil {
return err
}
diff --git a/x-pack/libbeat/licenser/elastic_fetcher.go b/x-pack/libbeat/licenser/elastic_fetcher.go
index 6ffa5f6fa37..b2c855df6b7 100644
--- a/x-pack/libbeat/licenser/elastic_fetcher.go
+++ b/x-pack/libbeat/licenser/elastic_fetcher.go
@@ -18,9 +18,9 @@ import (
"github.com/elastic/beats/v7/libbeat/logp"
)
-const xPackURL = "/_license"
+const licenseURL = "/_license"
-// params defaults query parameters to send to the '_xpack' endpoint by default we only need
+// params defaults query parameters to send to the '_license' endpoint by default we only need
// machine parseable data.
var params = map[string]string{
"human": "false",
@@ -88,12 +88,12 @@ func NewElasticFetcher(client esclient) *ElasticFetcher {
return &ElasticFetcher{client: client, log: logp.NewLogger("elasticfetcher")}
}
-// Fetch retrieves the license information from an Elasticsearch Client, it will call the `_xpack`
-// end point and will return a parsed license. If the `_xpack` endpoint is unreacheable we will
+// Fetch retrieves the license information from an Elasticsearch Client, it will call the `_license`
+// endpoint and will return a parsed license. If the `_license` endpoint is unreacheable we will
// return the OSS License otherwise we return an error.
func (f *ElasticFetcher) Fetch() (*License, error) {
- status, body, err := f.client.Request("GET", xPackURL, "", params, nil)
- // When we are running an OSS release of elasticsearch the _xpack endpoint will return a 405,
+ status, body, err := f.client.Request("GET", licenseURL, "", params, nil)
+ // When we are running an OSS release of elasticsearch the _license endpoint will return a 405,
// "Method Not Allowed", so we return the default OSS license.
if status == http.StatusBadRequest {
f.log.Debug("Received 'Bad request' (400) response from server, fallback to OSS license")
diff --git a/x-pack/libbeat/licenser/es_callback.go b/x-pack/libbeat/licenser/es_callback.go
index 0ca99db8f5f..06cc055083c 100644
--- a/x-pack/libbeat/licenser/es_callback.go
+++ b/x-pack/libbeat/licenser/es_callback.go
@@ -30,7 +30,7 @@ func Enforce(name string, checks ...CheckFunc) {
license, err := fetcher.Fetch()
if err != nil {
- return errors.Wrapf(err, "cannot retrieve the elasticsearch license from the /_xpack endpoint, "+
+ return errors.Wrapf(err, "cannot retrieve the elasticsearch license from the /_license endpoint, "+
"%s requires the default distribution of Elasticsearch. Please make the endpoint accessible "+
"to %s so it can verify the license.", name, name)
}
diff --git a/x-pack/metricbeat/Makefile b/x-pack/metricbeat/Makefile
index 019d3b9309a..c77d4c68517 100644
--- a/x-pack/metricbeat/Makefile
+++ b/x-pack/metricbeat/Makefile
@@ -1,3 +1,8 @@
ES_BEATS ?= ../..
include $(ES_BEATS)/dev-tools/make/mage.mk
+
+# Creates a new metricset. Requires the params MODULE and METRICSET
+.PHONY: create-metricset
+create-metricset:
+ mage createMetricset
diff --git a/x-pack/metricbeat/magefile.go b/x-pack/metricbeat/magefile.go
index ffd40949d70..992e4d6d1fa 100644
--- a/x-pack/metricbeat/magefile.go
+++ b/x-pack/metricbeat/magefile.go
@@ -25,6 +25,8 @@ import (
"github.com/elastic/beats/v7/dev-tools/mage/target/unittest"
// mage:import
"github.com/elastic/beats/v7/dev-tools/mage/target/test"
+ // mage:import
+ _ "github.com/elastic/beats/v7/metricbeat/scripts/mage/target/metricset"
)
func init() {
diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml
index 3fba65dbee6..d736b844393 100644
--- a/x-pack/metricbeat/metricbeat.reference.yml
+++ b/x-pack/metricbeat/metricbeat.reference.yml
@@ -843,7 +843,7 @@ metricbeat.modules:
#--------------------------------- Kvm Module ---------------------------------
- module: kvm
- metricsets: ["dommemstat"]
+ metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]