Repository: cloudprober/cloudprober

Issue:
no DNS resolution when using file based targets

i'm configuring probes using file-based targets, and it seems like DNS resolution isn't happening when the targets are specified as domain names.

### here's my configuration:

```cfg
surfacer {
  type: PROBESTATUS
  metrics_buffer_size: 1000000
  probestatus_surfacer {
    max_targets_per_probe: 500
  }
}

surfacer {
  type: PROMETHEUS
  prometheus_surfacer {
    metrics_prefix: "cloudprober_"
    metrics_buffer_size: 1000000
  }
  add_failure_metric: true
}

# include "probe-config-icmp.cfg"
probe {
  name: "icmp-1s"
  type: PING
  interval_msec: 1000
  timeout_msec: 1000
  targets {
    file_targets {
      file_path: "./targets-icmp.yaml"
      re_eval_sec: 60
    }
    dns_options {
      server: "8.8.8.8"
      ttl_sec: 300
      max_cache_age_sec: 3600
    }
  }
  latency_unit: "ms"
  ip_version: IPV4
  ping_probe {
  }
  additional_label {
    key: "group"
    value: "@target.label.group@"
  }
}

# include "probe-config-tcp.cfg"
probe {
  name: "tcp-30s"
  type: TCP
  interval_msec: 30000
  timeout_msec: 30000
  targets {
    file_targets {
      file_path: "./targets-tcp.yaml"
      re_eval_sec: 60
    }
    dns_options {
      server: "8.8.8.8"
      ttl_sec: 300
      max_cache_age_sec: 3600
    }
  }
  tcp_probe {
    resolve_first: true
  }
  latency_unit: "ms"
  additional_label {
    key: "group"
    value: "@target.label.group@"
  }
}
```


yaml `targets-icmp.yaml`

```yaml
---
resource:
- name: time.google.com.
  labels:
    group: google
```

yaml `targets-tcp.yaml`


```
---
resource:
- name: fcm.googleapis.com.
  port: 443
  labels:
    group: google
```

and here’s the output:

```
time=2025-07-16T08:47:22.192Z level=INFO source=targets/resolver/resolver.go:287 msg="Overriding default resolver with: 8.8.8.8" system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:22.192Z level=INFO source=internal/rds/file/file.go:237 msg="file_provider: Determined file format from file name: YAML" system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:22.192Z level=INFO source=prober/prober.go:119 msg="Creating a PING probe: icmp-1s" system=cloudprober component=global
time=2025-07-16T08:47:22.192Z level=INFO source=targets/resolver/resolver.go:287 msg="Overriding default resolver with: 8.8.8.8" system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:22.192Z level=INFO source=internal/rds/file/file.go:237 msg="file_provider: Determined file format from file name: YAML" system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:22.192Z level=INFO source=prober/prober.go:119 msg="Creating a TCP probe: tcp-30s" system=cloudprober component=global
time=2025-07-16T08:47:22.192Z level=INFO source=internal/rds/file/file.go:200 msg="file_provider(./targets-icmp.yaml): Read 1 endpoints" system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:22.193Z level=INFO source=surfacers/internal/probestatus/probestatus.go:210 msg="Initialized status surfacer at the URL: /status" system=cloudprober surfacer=probestatus
time=2025-07-16T08:47:22.193Z level=INFO source=internal/rds/file/file.go:200 msg="file_provider(./targets-tcp.yaml): Read 1 endpoints" system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:22.196Z level=INFO source=surfacers/internal/prometheus/prometheus.go:204 msg="Initialized prometheus exporter at the URL: /metrics" system=cloudprober surfacer=prometheus
time=2025-07-16T08:47:22.198Z level=INFO source=internal/sysvars/sysvars.go:201 msg="1752655642 labels=ptype=sysvars,probe=sysvars hostname=\"@@@@@\" start_timestamp=\"1752655642\" version=\"v0.14.0\"" system=cloudprober component=sysvars
time=2025-07-16T08:47:22.198Z level=INFO source=prober/prober.go:193 msg="Starting probe: icmp-1s" system=cloudprober component=global
time=2025-07-16T08:47:23.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:28.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:30.412Z level=INFO source=prober/prober.go:193 msg="Starting probe: tcp-30s" system=cloudprober component=global
time=2025-07-16T08:47:30.412Z level=INFO source=probes/common/sched/sched.go:102 msg="Targets update interval: 1m0s" system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:30.412Z level=INFO source=probes/common/sched/sched.go:200 msg="Probe(tcp-30s) targets updated: map[fcm.googleapis.com.__443_group:group:ADD]" system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:30.412Z level=ERROR source=probes/tcp/tcp.go:218 msg="target: fcm.googleapis.com., resolve error: no IP address for the resource: fcm.googleapis.com." system=cloudprober probe=tcp-30s
time=2025-07-16T08:47:33.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:38.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:43.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:48.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:53.198Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:47:58.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:48:00.413Z level=ERROR source=probes/tcp/tcp.go:218 msg="target: fcm.googleapis.com., resolve error: no IP address for the resource: fcm.googleapis.com." system=cloudprober probe=tcp-30s
time=2025-07-16T08:48:03.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
time=2025-07-16T08:48:08.199Z level=WARN source=probes/ping/ping.go:233 msg="Bad target: time.google.com.. Err: no IP address for the resource: time.google.com." system=cloudprober probe=icmp-1s
```

i'm not running on GCE/Kubernetes, or any cloud environment
is there another option or workaround to support DNS based dynamic hosts in this setup?

i am looking to monitor 100+ domain named hosts

Hints from issue comments:
@manugarg: Thanks @kerus1024! I could confirm that this is a bug. I think I know what's going on. I'll add more details shortly.@manugarg: I've a PR with the fix: https://github.com/cloudprober/cloudprober/pull/1100

Solution patch:
diff --git a/internal/rds/file/file.go b/internal/rds/file/file.go
index 9934c46e..f512d988 100644
--- a/internal/rds/file/file.go
+++ b/internal/rds/file/file.go
@@ -207,6 +207,8 @@ func (ls *lister) refresh() error {
 		}
 		if e.IP != nil {
 			epRes.Ip = proto.String(e.IP.String())
+		} else {
+			epRes.Ip = proto.String(e.Name)
 		}
 		if e.Port != 0 {
 			epRes.Port = proto.Int32(int32(e.Port))



Test patch:
diff --git a/internal/rds/file/testdata/testdata.go b/internal/rds/file/testdata/testdata.go
index 7b91100d..8cd41d23 100644
--- a/internal/rds/file/testdata/testdata.go
+++ b/internal/rds/file/testdata/testdata.go
@@ -52,6 +52,7 @@ var ExpectedResources = []*rdspb.Resource{
 	},
 	{
 		Name: proto.String("web-1"),
+		Ip:   proto.String("web-1"),
 		Port: proto.Int32(80),
 		Labels: map[string]string{
 			"__cp_host__":   "cloudprober.org",
diff --git a/targets/file/file_test.go b/targets/file/file_test.go
index ed3f4567..9fed3d32 100644
--- a/targets/file/file_test.go
+++ b/targets/file/file_test.go
@@ -15,13 +15,13 @@
 package file
 
 import (
-	"reflect"
 	"testing"
 
 	"github.com/cloudprober/cloudprober/internal/rds/file/testdata"
 	rdspb "github.com/cloudprober/cloudprober/internal/rds/proto"
 	"github.com/cloudprober/cloudprober/targets/endpoint"
 	configpb "github.com/cloudprober/cloudprober/targets/file/proto"
+	"github.com/stretchr/testify/assert"
 	"google.golang.org/protobuf/proto"
 )
 
@@ -64,25 +64,14 @@ func TestListEndpointsWithFilter(t *testing.T) {
 			if len(got) != len(test.wantEndpoints) {
 				t.Fatalf("Got endpoints: %d, expected: %d", len(got), len(test.wantEndpoints))
 			}
+
 			for i := range test.wantEndpoints {
 				want := test.wantEndpoints[i]
 
-				if got[i].Name != want.Name || got[i].Port != want.Port || !reflect.DeepEqual(got[i].Labels, want.Labels) {
-					t.Errorf("ListResources: got:\n%v\nexpected:\n%v", got[i], want)
-				}
-			}
-
-			for _, ep := range got {
-				if testExpectedIP[ep.Name] != "" {
-					resolvedIP, err := ft.Resolve(ep.Name, 0)
-					if err != nil {
-						t.Errorf("unexpected error while resolving %s: %v", ep.Name, err)
-					}
-					ip := resolvedIP.String()
-					if ip != testExpectedIP[ep.Name] {
-						t.Errorf("ft.Resolve(%s): got=%s, expected=%s", ep.Name, ip, testExpectedIP[ep.Name])
-					}
-				}
+				assert.Equal(t, got[i].Name, want.Name)
+				assert.Equal(t, got[i].Port, want.Port)
+				assert.Equal(t, got[i].Labels, want.Labels)
+				assert.Equal(t, got[i].IP.String(), want.IP.String())
 			}
 		})
 	}