Repository: VictoriaMetrics/operator

Issue:
ScrapeInterval not set in VMScrapeConfig?
I have the following `ScrapeConfig`:

```
apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
  name: foo
spec:
  scrapeInterval: 30m
  staticConfigs:
    - labels:
        job: external-monitoring
      targets:
        - "http://foo/metrics"
```
 
And the `VMScrapeConfig` generated by vm-operator is missing the scrape interval (I suppose it should have `spec.interval` set from `spec.scrapeInterval`), why is this?

```
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMScrapeConfig
metadata:
  annotations:
  creationTimestamp: "2025-11-28T08:29:13Z"
  generation: 1
  name: foo
  namespace: monitoring
  resourceVersion: "12936439"
  uid: 97f97b43-55ca-47a4-85fb-5693dcb75ddc
spec:
  staticConfigs:
  - labels:
      job: external-monitoring
    targets:
    - http://foo/metrics
status:
  conditions:
  - lastTransitionTime: "2025-11-28T08:29:13Z"
    lastUpdateTime: "2025-11-28T08:29:13Z"
    observedGeneration: 1
    reason: ConfigParsedAndApplied
    status: "True"
    type: vm.victoriametrics.vmagent.victoriametrics.com/Applied
  observedGeneration: 1
  updateStatus: operational
```


Discussion:
@AndrewChubatiuk: it should be `scrape_interval`, not `scrapeInterval`@a-bali: It is `scrapeInterval` according to the [CRD](https://prometheus-operator.dev/docs/api-reference/api/#monitoring.coreos.com/v1alpha1.ScrapeConfig).@AndrewChubatiuk: your link points to prometheus operator CRDs, VM operator CRDs are [here](https://docs.victoriametrics.com/operator/api/#vmscrapeconfigspec-scrape_interval)@a-bali: But then, I have a valid `ScrapeConfig` as per the Prometheus CRD. I would expect vm-operator to generate a valid `VMScrapeConfig`, which it does, but it skips the `scrapeInterval` source field. And it should create a `scrape_interval` target field.@AndrewChubatiuk: yes, that's a bug, will add a PR with a fix soon@AndrewChubatiuk: fix is available in operator [v0.66.0 ](https://github.com/VictoriaMetrics/operator/releases/tag/v0.66.0)and released in helm chart [0.57.0](https://github.com/VictoriaMetrics/helm-charts/releases/tag/victoria-metrics-operator-0.57.0)

Solution patch:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index d9398500..2f429ac3 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -25,6 +25,7 @@ aliases:
 
 * BUGFIX: [vmalertmanager](https://docs.victoriametrics.com/operator/resources/vmalertmanager/): check `mute_time_intervals` in subroutes: See [#1618](https://github.com/VictoriaMetrics/operator/issues/1618).
 * BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): remove incorrect key argument in structured log for when the actual PVC storage size is larger than the currently configured size and properly indicate which is the new and which is the existing size: See PR [#1636](https://github.com/VictoriaMetrics/operator/pull/1636) for details.
+* BUGFIX: [converter](https://docs.victoriametrics.com/operator/integrations/prometheus/#objects-conversion): properly convert Prometheus ScrapeConfig `scrapeInterval` into VM ScrapeConfig `scrape_interval`. Before it was ignored. See [#1645](https://github.com/VictoriaMetrics/operator/issues/1645).
 
 * Dependency: [vmoperator](https://docs.victoriametrics.com/operator/): Updated default versions for VT apps to [v0.5.0](https://github.com/VictoriaMetrics/VictoriaTraces/releases/tag/v0.5.0) version.
 
diff --git a/internal/controller/operator/converter/v1alpha1/apis.go b/internal/controller/operator/converter/v1alpha1/apis.go
index 149d48c7..eb7b1805 100644
--- a/internal/controller/operator/converter/v1alpha1/apis.go
+++ b/internal/controller/operator/converter/v1alpha1/apis.go
@@ -145,6 +145,9 @@ func ConvertScrapeConfig(promscrapeConfig *promv1alpha1.ScrapeConfig, conf *conf
 	cs.Spec.RelabelConfigs = converter.ConvertRelabelConfig(promscrapeConfig.Spec.RelabelConfigs)
 	cs.Spec.MetricRelabelConfigs = converter.ConvertRelabelConfig(promscrapeConfig.Spec.MetricRelabelConfigs)
 	cs.Spec.Path = ptr.Deref(promscrapeConfig.Spec.MetricsPath, "")
+	if promscrapeConfig.Spec.ScrapeInterval != nil {
+		cs.Spec.ScrapeInterval = string(*promscrapeConfig.Spec.ScrapeInterval)
+	}
 
 	if promscrapeConfig.Spec.EnableCompression != nil {
 		cs.Spec.VMScrapeParams = &vmv1beta1.VMScrapeParams{



Test patch:
diff --git a/internal/controller/operator/converter/v1alpha1/apis_test.go b/internal/controller/operator/converter/v1alpha1/apis_test.go
index 36d8f0d0..361a14fe 100644
--- a/internal/controller/operator/converter/v1alpha1/apis_test.go
+++ b/internal/controller/operator/converter/v1alpha1/apis_test.go
@@ -131,7 +131,8 @@ func TestConvertScrapeConfig(t *testing.T) {
 					Username: corev1.SecretKeySelector{Key: "username"},
 					Password: corev1.SecretKeySelector{Key: "password"},
 				},
-				MetricsPath: ptr.To("/test"),
+				ScrapeInterval: promv1.DurationPointer("5m"),
+				MetricsPath:    ptr.To("/test"),
 				ProxyConfig: promv1.ProxyConfig{
 					ProxyURL: ptr.To("http://proxy.com"),
 				},
@@ -154,6 +155,7 @@ func TestConvertScrapeConfig(t *testing.T) {
 					HonorTimestamps: ptr.To(true),
 					VMScrapeParams:  &vmv1beta1.VMScrapeParams{DisableCompression: ptr.To(false)},
 					Path:            "/test",
+					ScrapeInterval:  "5m",
 				},
 				StaticConfigs: []vmv1beta1.StaticConfig{{
 					Targets: []string{"target-1", "target-2"},