Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discovery.linode component #5174

Merged
merged 11 commits into from
Sep 14, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Main (unreleased)
flow mode equivalent to static mode's `service_graphs` processor. (@ptodev)
- `discovery.consulagent` discovers scrape targets from Consul Agent. (@wildum)
- `discovery.kuma` discovers scrape targets from the Kuma control plane. (@tpaschalis)
- `discovery.linode` discovers scrape targets from the Linode API. (@captncraig)
- `discovery.marathon` discovers scrape targets from Marathon servers. (@wildum)
- `discovery.ionos` discovers scrape targets from the IONOS Cloud API. (@wildum)
- `discovery.triton` discovers scrape targets from Triton Container Monitor. (@erikbaranowski)
Expand Down
1 change: 1 addition & 0 deletions component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
_ "github.com/grafana/agent/component/discovery/kubelet" // Import discovery.kubelet
_ "github.com/grafana/agent/component/discovery/kubernetes" // Import discovery.kubernetes
_ "github.com/grafana/agent/component/discovery/kuma" // Import discovery.kuma
_ "github.com/grafana/agent/component/discovery/linode" // Import discovery.linode
_ "github.com/grafana/agent/component/discovery/marathon" // Import discovery.marathon
_ "github.com/grafana/agent/component/discovery/nerve" // Import discovery.nerve
_ "github.com/grafana/agent/component/discovery/nomad" // Import discovery.nomad
Expand Down
4 changes: 2 additions & 2 deletions component/discovery/kuma/kuma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ func TestValidateNoServers(t *testing.T) {
RefreshInterval: 10 * time.Second,
}
err := riverArgs.Validate()
require.Error(t, err, "fetch_timeout must be greater than 0")
require.ErrorContains(t, err, "fetch_timeout must be greater than 0")
})
t.Run("validate refresh interval", func(t *testing.T) {
riverArgs := Arguments{
FetchTimeout: 10 * time.Second,
}
err := riverArgs.Validate()
require.Error(t, err, "refresh_interval must be greater than 0")
require.ErrorContains(t, err, "refresh_interval must be greater than 0")
})
}
72 changes: 72 additions & 0 deletions component/discovery/linode/linode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package linode

import (
"fmt"
"time"

"github.com/grafana/agent/component"
"github.com/grafana/agent/component/common/config"
"github.com/grafana/agent/component/discovery"
"github.com/prometheus/common/model"
prom_discovery "github.com/prometheus/prometheus/discovery/linode"
)

func init() {
component.Register(component.Registration{
Name: "discovery.linode",
Args: Arguments{},
Exports: discovery.Exports{},

Build: func(opts component.Options, args component.Arguments) (component.Component, error) {
return New(opts, args.(Arguments))
},
})
}

// Arguments configure the discovery.linode component.
type Arguments struct {
RefreshInterval time.Duration `river:"refresh_interval,attr,optional"`
Port int `river:"port,attr,optional"`
TagSeparator string `river:"tag_separator,attr,optional"`
HTTPClientConfig config.HTTPClientConfig `river:",squash"`
}

// DefaultArguments is used to initialize default values for Arguments.
var DefaultArguments = Arguments{
TagSeparator: ",",
Port: 80,
RefreshInterval: 60 * time.Second,

HTTPClientConfig: config.DefaultHTTPClientConfig,
}

// SetToDefault implements river.Defaulter.
func (args *Arguments) SetToDefault() {
*args = DefaultArguments
}

// Validate implements river.Validator.
func (args *Arguments) Validate() error {
if args.RefreshInterval <= 0 {
return fmt.Errorf("refresh_interval must be greater than 0")
}
return args.HTTPClientConfig.Validate()
}

// Convert returns the upstream configuration struct.
func (args *Arguments) Convert() *prom_discovery.SDConfig {
return &prom_discovery.SDConfig{
RefreshInterval: model.Duration(args.RefreshInterval),
Port: args.Port,
TagSeparator: args.TagSeparator,
HTTPClientConfig: *(args.HTTPClientConfig.Convert()),
}
}

// New returns a new instance of a discovery.linode component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger)
})
}
50 changes: 50 additions & 0 deletions component/discovery/linode/linode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package linode

import (
"testing"
"time"

"github.com/grafana/agent/component/common/config"
"github.com/grafana/river"
promconfig "github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
)

func TestRiverConfig(t *testing.T) {
var exampleRiverConfig = `
refresh_interval = "10s"
port = 8080
tag_separator = ";"
`
var args Arguments
err := river.Unmarshal([]byte(exampleRiverConfig), &args)
require.NoError(t, err)
}

func TestConvert(t *testing.T) {
riverArgs := Arguments{
Port: 8080,
RefreshInterval: 15 * time.Second,
TagSeparator: ";",
HTTPClientConfig: config.HTTPClientConfig{
BearerToken: "FOO",
},
}

promArgs := riverArgs.Convert()
require.Equal(t, 8080, promArgs.Port)
require.Equal(t, model.Duration(15*time.Second), promArgs.RefreshInterval)
require.Equal(t, ";", promArgs.TagSeparator)
require.Equal(t, promconfig.Secret("FOO"), promArgs.HTTPClientConfig.BearerToken)
}

func TestValidate(t *testing.T) {
t.Run("validate RefreshInterval", func(t *testing.T) {
riverArgs := Arguments{
RefreshInterval: 0,
}
err := riverArgs.Validate()
require.ErrorContains(t, err, "refresh_interval must be greater than 0")
})
}
36 changes: 36 additions & 0 deletions converter/internal/prometheusconvert/linode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package prometheusconvert

import (
"time"

"github.com/grafana/agent/component/discovery"
"github.com/grafana/agent/component/discovery/linode"
"github.com/grafana/agent/converter/diag"
"github.com/grafana/agent/converter/internal/common"
prom_linode "github.com/prometheus/prometheus/discovery/linode"
)

func appendDiscoveryLinode(pb *prometheusBlocks, label string, sdConfig *prom_linode.SDConfig) discovery.Exports {
discoveryLinodeArgs := ToDiscoveryLinode(sdConfig)
name := []string{"discovery", "linode"}
block := common.NewBlockWithOverride(name, label, discoveryLinodeArgs)
pb.discoveryBlocks = append(pb.discoveryBlocks, newPrometheusBlock(block, name, label, "", ""))
return NewDiscoveryExports("discovery.linode." + label + ".targets")
}

func validateDiscoveryLinode(sdConfig *prom_linode.SDConfig) diag.Diagnostics {
return ValidateHttpClientConfig(&sdConfig.HTTPClientConfig)
}

func ToDiscoveryLinode(sdConfig *prom_linode.SDConfig) *linode.Arguments {
if sdConfig == nil {
return nil
}

return &linode.Arguments{
RefreshInterval: time.Duration(sdConfig.RefreshInterval),
Port: sdConfig.Port,
TagSeparator: sdConfig.TagSeparator,
HTTPClientConfig: *ToHttpClientConfig(&sdConfig.HTTPClientConfig),
}
}
4 changes: 4 additions & 0 deletions converter/internal/prometheusconvert/prometheusconvert.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
prom_gce "github.com/prometheus/prometheus/discovery/gce"
prom_ionos "github.com/prometheus/prometheus/discovery/ionos"
prom_kubernetes "github.com/prometheus/prometheus/discovery/kubernetes"
prom_linode "github.com/prometheus/prometheus/discovery/linode"
prom_marathon "github.com/prometheus/prometheus/discovery/marathon"
prom_docker "github.com/prometheus/prometheus/discovery/moby"
prom_scaleway "github.com/prometheus/prometheus/discovery/scaleway"
Expand Down Expand Up @@ -181,6 +182,9 @@ func AppendServiceDiscoveryConfigs(pb *prometheusBlocks, serviceDiscoveryConfig
case *prom_zk.ServersetSDConfig:
labelCounts["serverset"]++
exports = appendDiscoveryServerset(pb, common.LabelWithIndex(labelCounts["serverset"]-1, label), sdc)
case *prom_linode.SDConfig:
labelCounts["linode"]++
exports = appendDiscoveryLinode(pb, common.LabelWithIndex(labelCounts["linode"]-1, label), sdc)
case *prom_nerve.NerveSDConfig:
labelCounts["nerve"]++
exports = appendDiscoveryNerve(pb, common.LabelWithIndex(labelCounts["nerve"]-1, label), sdc)
Expand Down
34 changes: 34 additions & 0 deletions converter/internal/prometheusconvert/testdata/linode.river
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
discovery.linode "prometheus1" {
refresh_interval = "1m40s"
port = 8080
}

discovery.linode "prometheus2" { }

prometheus.scrape "prometheus1" {
targets = concat(
discovery.linode.prometheus1.targets,
[{
__address__ = "localhost:9090",
}],
)
forward_to = [prometheus.remote_write.default.receiver]
job_name = "prometheus1"
}

prometheus.scrape "prometheus2" {
targets = discovery.linode.prometheus2.targets
forward_to = [prometheus.remote_write.default.receiver]
job_name = "prometheus2"
}

prometheus.remote_write "default" {
endpoint {
name = "remote1"
url = "http://remote-write-url1"

queue_config { }

metadata_config { }
}
}
15 changes: 15 additions & 0 deletions converter/internal/prometheusconvert/testdata/linode.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
scrape_configs:
- job_name: "prometheus1"
static_configs:
- targets: ["localhost:9090"]
linode_sd_configs:
- refresh_interval: "100s"
port: 8080
- job_name: "prometheus2"
linode_sd_configs:
- {}

remote_write:
- name: "remote1"
url: "http://remote-write-url1"

3 changes: 3 additions & 0 deletions converter/internal/prometheusconvert/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
_ "github.com/prometheus/prometheus/discovery/install" // Register Prometheus SDs
prom_ionos "github.com/prometheus/prometheus/discovery/ionos"
prom_kubernetes "github.com/prometheus/prometheus/discovery/kubernetes"
prom_linode "github.com/prometheus/prometheus/discovery/linode"
prom_marathon "github.com/prometheus/prometheus/discovery/marathon"
prom_docker "github.com/prometheus/prometheus/discovery/moby"
prom_scaleway "github.com/prometheus/prometheus/discovery/scaleway"
Expand Down Expand Up @@ -110,6 +111,8 @@ func ValidateServiceDiscoveryConfigs(serviceDiscoveryConfigs prom_discover.Confi
diags.AddAll(validateDiscoveryLightsail(sdc))
case *prom_kuma.SDConfig:
diags.AddAll(validateDiscoveryKuma(sdc))
case *prom_linode.SDConfig:
diags.AddAll(validateDiscoveryLinode(sdc))
case *prom_triton.SDConfig:
diags.AddAll(validateDiscoveryTriton(sdc))
case *prom_scaleway.SDConfig:
Expand Down
2 changes: 1 addition & 1 deletion docs/sources/flow/reference/components/discovery.kuma.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Name | Type | Description
- [`oauth2` block][oauth2].

The following blocks are supported inside the definition of
`discovery.nomad`:
`discovery.kuma`:

Hierarchy | Block | Description | Required
--------- | ----- | ----------- | --------
Expand Down
Loading