Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion docs/resources/virtual_environment_metrics_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ resource "proxmox_virtual_environment_metrics_server" "graphite_server" {
port = 2003
type = "graphite"
}

resource "proxmox_virtual_environment_metrics_server" "opentelemetry_server" {
name = "example_opentelemetry_server"
server = "192.168.5.2"
port = 4318
type = "opentelemetry"
opentelemetry_proto = "https"
opentelemetry_path = "/v1/metrics"
}
```

<!-- schema generated by tfplugindocs -->
Expand All @@ -37,7 +46,7 @@ resource "proxmox_virtual_environment_metrics_server" "graphite_server" {
- `name` (String) Unique name that will be ID of this metric server in PVE.
- `port` (Number) Server network port.
- `server` (String) Server dns name or IP address.
- `type` (String) Plugin type. Choice is between `graphite` | `influxdb`.
- `type` (String) Plugin type. Choice is between `graphite` | `influxdb` | `opentelemetry`.

### Optional

Expand All @@ -52,6 +61,8 @@ resource "proxmox_virtual_environment_metrics_server" "graphite_server" {
- `influx_token` (String, Sensitive) The InfluxDB access token. Only necessary when using the http v2 api. If the v2 compatibility api is used, use `user:password` instead.
- `influx_verify` (Boolean) Set to `false` to disable certificate verification for https endpoints.
- `mtu` (Number) MTU (maximum transmission unit) for metrics transmission over UDP. If not set, PVE default is `1500` (allowed `512` - `65536`).
- `opentelemetry_path` (String) OpenTelemetry endpoint path (e.g., `/v1/metrics`).
- `opentelemetry_proto` (String) Protocol for OpenTelemetry. Choice is between `http` | `https` | `grpc`. If not set, PVE default is `http`.
- `timeout` (Number) TCP socket timeout in seconds. If not set, PVE default is `1`.

### Read-Only
Expand Down
18 changes: 18 additions & 0 deletions example/resource_virtual_environment_metrics_server.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,21 @@ resource "proxmox_virtual_environment_metrics_server" "graphite_server2" {
timeout = 5
graphite_proto = "udp"
}

resource "proxmox_virtual_environment_metrics_server" "opentelemetry_server" {
name = "example_opentelemetry_server"
server = "192.168.5.2"
port = 4318
type = "opentelemetry"
opentelemetry_proto = "http"
opentelemetry_path = "/v1/metrics"
}

resource "proxmox_virtual_environment_metrics_server" "opentelemetry_server_https" {
name = "example_opentelemetry_server_https"
server = "192.168.5.3"
port = 4319
type = "opentelemetry"
opentelemetry_proto = "https"
opentelemetry_path = "/v1/metrics"
}
10 changes: 9 additions & 1 deletion fwprovider/cluster/metrics/datasource_metrics_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,15 @@ func (r *metricsServerDatasource) Schema(
Computed: true,
},
"type": schema.StringAttribute{
Description: "Plugin type. Either `graphite` or `influxdb`.",
Description: "Plugin type. Either `graphite`, `influxdb`, or `opentelemetry`.",
Computed: true,
},
"opentelemetry_proto": schema.StringAttribute{
Description: "Protocol for OpenTelemetry. Choice is between `http` | `https` | `grpc`.",
Computed: true,
},
"opentelemetry_path": schema.StringAttribute{
Description: "OpenTelemetry endpoint path (e.g., `/v1/metrics`).",
Computed: true,
},
},
Expand Down
22 changes: 16 additions & 6 deletions fwprovider/cluster/metrics/metrics_server_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type metricsServerModel struct {
InfluxVerify types.Bool `tfsdk:"influx_verify"`
GraphitePath types.String `tfsdk:"graphite_path"`
GraphiteProto types.String `tfsdk:"graphite_proto"`
OTelProto types.String `tfsdk:"opentelemetry_proto"`
OTelPath types.String `tfsdk:"opentelemetry_path"`
}

func boolToInt64Ptr(boolPtr *bool) *int64 {
Expand Down Expand Up @@ -85,6 +87,8 @@ func (m *metricsServerModel) importFromAPI(name string, data *metrics.ServerData
m.InfluxVerify = types.BoolPointerValue(int64ToBoolPtr(data.Verify))
m.GraphitePath = types.StringPointerValue(data.Path)
m.GraphiteProto = types.StringPointerValue(data.Proto)
m.OTelProto = types.StringPointerValue(data.OTelProto)
m.OTelPath = types.StringPointerValue(data.OTelPath)
}

// toAPIRequestBody creates metrics server request data for PUT and POST requests.
Expand All @@ -108,17 +112,21 @@ func (m *metricsServerModel) toAPIRequestBody() *metrics.ServerRequestData {
data.Verify = boolToInt64Ptr(m.InfluxVerify.ValueBoolPointer())
data.Path = m.GraphitePath.ValueStringPointer()
data.Proto = m.GraphiteProto.ValueStringPointer()
data.OTelProto = m.OTelProto.ValueStringPointer()
data.OTelPath = m.OTelPath.ValueStringPointer()

return data
}

type metricsServerDatasourceModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Disable types.Bool `tfsdk:"disable"`
Port types.Int64 `tfsdk:"port"`
Server types.String `tfsdk:"server"`
Type types.String `tfsdk:"type"`
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Disable types.Bool `tfsdk:"disable"`
Port types.Int64 `tfsdk:"port"`
Server types.String `tfsdk:"server"`
Type types.String `tfsdk:"type"`
OTelProto types.String `tfsdk:"opentelemetry_proto"`
OTelPath types.String `tfsdk:"opentelemetry_path"`
}

// importFromAPI takes data from metrics server PVE API response and set fields based on it.
Expand All @@ -131,4 +139,6 @@ func (m *metricsServerDatasourceModel) importFromAPI(name string, data *metrics.
m.Port = types.Int64Value(data.Port)
m.Server = types.StringValue(data.Server)
m.Type = types.StringPointerValue(data.Type)
m.OTelProto = types.StringPointerValue(data.OTelProto)
m.OTelPath = types.StringPointerValue(data.OTelPath)
}
18 changes: 16 additions & 2 deletions fwprovider/cluster/metrics/resource_metrics_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ func (r *metricsServerResource) Schema(
Default: nil,
},
"type": schema.StringAttribute{
Description: "Plugin type. Choice is between `graphite` | `influxdb`.",
Description: "Plugin type. Choice is between `graphite` | `influxdb` | `opentelemetry`.",
Required: true,
Validators: []validator.String{stringvalidator.OneOf("graphite", "influxdb")},
Validators: []validator.String{stringvalidator.OneOf("graphite", "influxdb", "opentelemetry")},
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Expand Down Expand Up @@ -175,6 +175,18 @@ func (r *metricsServerResource) Schema(
Optional: true,
Default: nil,
},
"opentelemetry_proto": schema.StringAttribute{
Description: "Protocol for OpenTelemetry. Choice is between `http` | `https`. " +
"If not set, PVE default is `http`.",
Validators: []validator.String{stringvalidator.OneOf("http", "https")},
Optional: true,
Default: nil,
},
"opentelemetry_path": schema.StringAttribute{
Description: "OpenTelemetry endpoint path (e.g., `/v1/metrics`).",
Optional: true,
Default: nil,
},
Comment on lines +185 to +189
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The opentelemetry_path attribute is only applicable for http and https protocols, and not for grpc. To improve user experience and prevent misconfiguration, consider adding a custom validator to enforce this. The validator should produce an error if opentelemetry_path is set when opentelemetry_proto is grpc.

},
}
}
Expand Down Expand Up @@ -277,6 +289,8 @@ func (r *metricsServerResource) Update(
attribute.CheckDelete(plan.InfluxVerify, state.InfluxVerify, &toDelete, "verify-certificate")
attribute.CheckDelete(plan.GraphitePath, state.GraphitePath, &toDelete, "path")
attribute.CheckDelete(plan.GraphiteProto, state.GraphiteProto, &toDelete, "proto")
attribute.CheckDelete(plan.OTelProto, state.OTelProto, &toDelete, "otel-protocol")
attribute.CheckDelete(plan.OTelPath, state.OTelPath, &toDelete, "otel-path")

reqData := plan.toAPIRequestBody()
reqData.Delete = &toDelete
Expand Down
51 changes: 51 additions & 0 deletions fwprovider/cluster/metrics/resource_metrics_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func TestAccResourceMetricsServer(t *testing.T) {
"influx_verify",
"graphite_path",
"graphite_proto",
"opentelemetry_proto",
"opentelemetry_path",
}),
),
},
Expand Down Expand Up @@ -88,6 +90,8 @@ func TestAccResourceMetricsServer(t *testing.T) {
"influx_verify",
"graphite_path",
"graphite_proto",
"opentelemetry_proto",
"opentelemetry_path",
}),
),
},
Expand Down Expand Up @@ -121,6 +125,8 @@ func TestAccResourceMetricsServer(t *testing.T) {
"influx_verify",
"graphite_path",
"graphite_proto",
"opentelemetry_proto",
"opentelemetry_path",
}),
),
},
Expand Down Expand Up @@ -165,6 +171,51 @@ func TestAccResourceMetricsServer(t *testing.T) {
),
},
}},
{"create opentelemetry metrics server & import it", []resource.TestStep{
{
ResourceName: "proxmox_virtual_environment_metrics_server.acc_otel_server",
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_metrics_server" "acc_otel_server" {
name = "acc_example_otel_server"
server = "192.168.3.2"
port = 4318
type = "opentelemetry"
opentelemetry_proto = "http"
}`),
},
{
ResourceName: "proxmox_virtual_environment_metrics_server.acc_otel_server",
ImportState: true,
ImportStateVerify: true,
},
}},
{"create opentelemetry metrics server & test datasource", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_metrics_server" "acc_otel_server2" {
name = "acc_example_otel_server2"
server = "192.168.3.2"
port = 4318
type = "opentelemetry"
opentelemetry_proto = "https"
opentelemetry_path = "/v1/metrics"
}
data "proxmox_virtual_environment_metrics_server" "acc_otel_server2" {
name = proxmox_virtual_environment_metrics_server.acc_otel_server2.name
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("data.proxmox_virtual_environment_metrics_server.acc_otel_server2", map[string]string{
"id": "acc_example_otel_server2",
"name": "acc_example_otel_server2",
"port": "4318",
"server": "192.168.3.2",
"type": "opentelemetry",
"opentelemetry_proto": "https",
"opentelemetry_path": "/v1/metrics",
}),
),
},
}},
}

for _, tt := range tests {
Expand Down
4 changes: 4 additions & 0 deletions proxmox/cluster/metrics/server_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type ServerData struct {
// graphite only options
Path *string `json:"path,omitempty" url:"path,omitempty"`
Proto *string `json:"proto,omitempty" url:"proto,omitempty"`

// opentelemetry only options
OTelProto *string `json:"otel-protocol,omitempty" url:"otel-protocol,omitempty"`
OTelPath *string `json:"otel-path,omitempty" url:"otel-path,omitempty"`
}

// ServerResponseBody contains the body from a metrics server response.
Expand Down