Add force preferred ip protocol (#382)
authorPascal Gauthier <pgauthier@nihilisme.ca>
Fri, 7 Dec 2018 15:20:36 +0000 (10:20 -0500)
committerBrian Brazil <brian.brazil@robustperception.io>
Fri, 7 Dec 2018 15:20:36 +0000 (15:20 +0000)
Signed-off-by: Pascal Gauthier <pgauthier@nihilisme.ca>
12 files changed:
CONFIGURATION.md
config/config.go
config/testdata/blackbox-good.yml
example.yml
prober/dns.go
prober/dns_test.go
prober/http.go
prober/http_test.go
prober/icmp.go
prober/tcp.go
prober/tcp_test.go
prober/utils.go

index ed16383606ae5b63277b82dbe2b29fadabdd001b..c261c75ea13f303d41f267a73a34ccc97b2276eb 100644 (file)
@@ -84,8 +84,9 @@ The other placeholders are specified separately.
   # HTTP proxy server to use to connect to the targets.
   [ proxy_url: <string> ]
 
-  # The preferred IP protocol of the HTTP probe (ip4, ip6).
+  # The IP protocol of the HTTP probe (ip4, ip6).
   [ preferred_ip_protocol: <string> | default = "ip6" ]
+  [ ip_protocol_fallback: <boolean | default = true> ]
 
   # The body of the HTTP request used in probe.
   body: [ <string> ]
@@ -97,8 +98,9 @@ The other placeholders are specified separately.
 
 ```yml
 
-# The preferred IP protocol of the TCP probe (ip4, ip6).
+# The IP protocol of the TCP probe (ip4, ip6).
 [ preferred_ip_protocol: <string> | default = "ip6" ]
+[ ip_protocol_fallback: <boolean | default = true> ]
 
 # The source IP address.
 [ source_ip_address: <string> ]
@@ -125,8 +127,9 @@ tls_config:
 
 ```yml
 
-# The preferred IP protocol of the DNS probe (ip4, ip6).
+# The IP protocol of the DNS probe (ip4, ip6).
 [ preferred_ip_protocol: <string> | default = "ip6" ]
+[ ip_protocol_fallback: <boolean | default = true> ]
 
 # The source IP address.
 [ source_ip_address: <string> ]
@@ -171,8 +174,9 @@ validate_additional_rrs:
 
 ```yml
 
-# The preferred IP protocol of the ICMP probe (ip4, ip6).
+# The IP protocol of the ICMP probe (ip4, ip6).
 [ preferred_ip_protocol: <string> | default = "ip6" ]
+[ ip_protocol_fallback: <boolean | default = true> ]
 
 # The source IP address.
 [ source_ip_address: <string> ]
index 1961b5321cbcca05bc1753cdc32f4f5a9984e969..2bd5d9469e57594ea92b53819dd86031d57e2456 100644 (file)
@@ -54,7 +54,8 @@ type HTTPProbe struct {
        // Defaults to 2xx.
        ValidStatusCodes       []int                   `yaml:"valid_status_codes,omitempty"`
        ValidHTTPVersions      []string                `yaml:"valid_http_versions,omitempty"`
-       PreferredIPProtocol    string                  `yaml:"preferred_ip_protocol,omitempty"`
+       IPProtocol             string                  `yaml:"preferred_ip_protocol,omitempty"`
+       IPProtocolFallback     bool                    `yaml:"ip_protocol_fallback,omitempty"`
        NoFollowRedirects      bool                    `yaml:"no_follow_redirects,omitempty"`
        FailIfSSL              bool                    `yaml:"fail_if_ssl,omitempty"`
        FailIfNotSSL           bool                    `yaml:"fail_if_not_ssl,omitempty"`
@@ -73,30 +74,33 @@ type QueryResponse struct {
 }
 
 type TCPProbe struct {
-       PreferredIPProtocol string           `yaml:"preferred_ip_protocol,omitempty"`
-       SourceIPAddress     string           `yaml:"source_ip_address,omitempty"`
-       QueryResponse       []QueryResponse  `yaml:"query_response,omitempty"`
-       TLS                 bool             `yaml:"tls,omitempty"`
-       TLSConfig           config.TLSConfig `yaml:"tls_config,omitempty"`
+       IPProtocol         string           `yaml:"preferred_ip_protocol,omitempty"`
+       IPProtocolFallback bool             `yaml:"ip_protocol_fallback,omitempty"`
+       SourceIPAddress    string           `yaml:"source_ip_address,omitempty"`
+       QueryResponse      []QueryResponse  `yaml:"query_response,omitempty"`
+       TLS                bool             `yaml:"tls,omitempty"`
+       TLSConfig          config.TLSConfig `yaml:"tls_config,omitempty"`
 }
 
 type ICMPProbe struct {
-       PreferredIPProtocol string `yaml:"preferred_ip_protocol,omitempty"` // Defaults to "ip6".
-       SourceIPAddress     string `yaml:"source_ip_address,omitempty"`
-       PayloadSize         int    `yaml:"payload_size,omitempty"`
-       DontFragment        bool   `yaml:"dont_fragment,omitempty"`
+       IPProtocol         string `yaml:"preferred_ip_protocol,omitempty"` // Defaults to "ip6".
+       IPProtocolFallback bool   `yaml:"ip_protocol_fallback,omitempty"`
+       SourceIPAddress    string `yaml:"source_ip_address,omitempty"`
+       PayloadSize        int    `yaml:"payload_size,omitempty"`
+       DontFragment       bool   `yaml:"dont_fragment,omitempty"`
 }
 
 type DNSProbe struct {
-       PreferredIPProtocol string         `yaml:"preferred_ip_protocol,omitempty"`
-       SourceIPAddress     string         `yaml:"source_ip_address,omitempty"`
-       TransportProtocol   string         `yaml:"transport_protocol,omitempty"`
-       QueryName           string         `yaml:"query_name,omitempty"`
-       QueryType           string         `yaml:"query_type,omitempty"`   // Defaults to ANY.
-       ValidRcodes         []string       `yaml:"valid_rcodes,omitempty"` // Defaults to NOERROR.
-       ValidateAnswer      DNSRRValidator `yaml:"validate_answer_rrs,omitempty"`
-       ValidateAuthority   DNSRRValidator `yaml:"validate_authority_rrs,omitempty"`
-       ValidateAdditional  DNSRRValidator `yaml:"validate_additional_rrs,omitempty"`
+       IPProtocol         string         `yaml:"preferred_ip_protocol,omitempty"`
+       IPProtocolFallback bool           `yaml:"ip_protocol_fallback,omitempty"`
+       SourceIPAddress    string         `yaml:"source_ip_address,omitempty"`
+       TransportProtocol  string         `yaml:"transport_protocol,omitempty"`
+       QueryName          string         `yaml:"query_name,omitempty"`
+       QueryType          string         `yaml:"query_type,omitempty"`   // Defaults to ANY.
+       ValidRcodes        []string       `yaml:"valid_rcodes,omitempty"` // Defaults to NOERROR.
+       ValidateAnswer     DNSRRValidator `yaml:"validate_answer_rrs,omitempty"`
+       ValidateAuthority  DNSRRValidator `yaml:"validate_authority_rrs,omitempty"`
+       ValidateAdditional DNSRRValidator `yaml:"validate_additional_rrs,omitempty"`
 }
 
 type DNSRRValidator struct {
index af15e67a66fe16e7ca88912fb7c159c7ef1ec223..d0a1f0cc83633d5f07b57bcfbd0994d2f565953c 100644 (file)
@@ -63,5 +63,6 @@ modules:
     dns:
       query_name: example.com
       preferred_ip_protocol: ip4
+      ip_protocol_fallback: false
       validate_answer_rrs:
         fail_if_matches_regexp: [test]
index 17beee045cf684f010f8f612b12d5470fac864f7..39786fb168bf85f6a4b744c979d25888551a865a 100644 (file)
@@ -19,6 +19,7 @@ modules:
       tls_config:
         insecure_skip_verify: false
       preferred_ip_protocol: "ip4" # defaults to "ip6"
+      ip_protocol_fallback: false  # no fallback to "ip6"
   http_post_2xx:
     prober: http
     timeout: 5s
@@ -120,5 +121,5 @@ modules:
     prober: dns
     dns:
       transport_protocol: "tcp" # defaults to "udp"
-      preferred_ip_protocol: "ip4" #  defaults to "ip6"
+      preferred_ip_protocol: "ip4" # defaults to "ip6"
       query_name: "www.prometheus.io"
index d11aa640700cfb63d1f95b5e874a35a7c4328076..c5078f68d8d467314176d996f8f386e06f213e93 100644 (file)
@@ -129,7 +129,7 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry
                        port = "53"
                        targetAddr = target
                }
-               ip, _, err = chooseProtocol(module.DNS.PreferredIPProtocol, targetAddr, registry, logger)
+               ip, _, err = chooseProtocol(module.DNS.IPProtocol, module.DNS.IPProtocolFallback, targetAddr, registry, logger)
                if err != nil {
                        level.Error(logger).Log("msg", "Error resolving address", "err", err)
                        return false
index f0b6f4085f2deaf3ebeb502299de2f5cc42878b5..525d44e6700fb80a5365d5e4b9117b87a9f70a80 100644 (file)
@@ -91,21 +91,21 @@ func TestRecursiveDNSResponse(t *testing.T) {
        }{
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                        }, true,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               ValidRcodes:         []string{"SERVFAIL", "NXDOMAIN"},
+                               IPProtocol:  "ipv4",
+                               QueryName:   "example.com",
+                               ValidRcodes: []string{"SERVFAIL", "NXDOMAIN"},
                        }, false,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAnswer: config.DNSRRValidator{
                                        FailIfMatchesRegexp:    []string{".*7200.*"},
                                        FailIfNotMatchesRegexp: []string{".*3600.*"},
@@ -114,8 +114,8 @@ func TestRecursiveDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAuthority: config.DNSRRValidator{
                                        FailIfMatchesRegexp: []string{".*7200.*"},
                                },
@@ -123,8 +123,8 @@ func TestRecursiveDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAdditional: config.DNSRRValidator{
                                        FailIfNotMatchesRegexp: []string{".*3600.*"},
                                },
@@ -217,27 +217,27 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
        }{
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                        }, true,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               QueryType:           "SOA",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
+                               QueryType:  "SOA",
                        }, true,
                }, {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               ValidRcodes:         []string{"SERVFAIL", "NXDOMAIN"},
+                               IPProtocol:  "ipv4",
+                               QueryName:   "example.com",
+                               ValidRcodes: []string{"SERVFAIL", "NXDOMAIN"},
                        }, false,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAnswer: config.DNSRRValidator{
                                        FailIfMatchesRegexp:    []string{".*3600.*"},
                                        FailIfNotMatchesRegexp: []string{".*3600.*"},
@@ -246,8 +246,8 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAnswer: config.DNSRRValidator{
                                        FailIfMatchesRegexp:    []string{".*7200.*"},
                                        FailIfNotMatchesRegexp: []string{".*7200.*"},
@@ -256,8 +256,8 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAuthority: config.DNSRRValidator{
                                        FailIfNotMatchesRegexp: []string{"ns.*.isp.net"},
                                },
@@ -265,8 +265,8 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAdditional: config.DNSRRValidator{
                                        FailIfNotMatchesRegexp: []string{"^ns.*.isp"},
                                },
@@ -274,8 +274,8 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                                ValidateAdditional: config.DNSRRValidator{
                                        FailIfMatchesRegexp: []string{"^ns.*.isp"},
                                },
@@ -321,29 +321,29 @@ func TestServfailDNSResponse(t *testing.T) {
        }{
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
                        }, false,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               ValidRcodes:         []string{"SERVFAIL", "NXDOMAIN"},
+                               IPProtocol:  "ipv4",
+                               QueryName:   "example.com",
+                               ValidRcodes: []string{"SERVFAIL", "NXDOMAIN"},
                        }, true,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               QueryType:           "NOT_A_VALID_QUERY_TYPE",
+                               IPProtocol: "ipv4",
+                               QueryName:  "example.com",
+                               QueryType:  "NOT_A_VALID_QUERY_TYPE",
                        }, false,
                },
                {
                        config.DNSProbe{
-                               PreferredIPProtocol: "ipv4",
-                               QueryName:           "example.com",
-                               ValidRcodes:         []string{"NOT_A_VALID_RCODE"},
+                               IPProtocol:  "ipv4",
+                               QueryName:   "example.com",
+                               ValidRcodes: []string{"NOT_A_VALID_RCODE"},
                        }, false,
                },
        }
@@ -398,9 +398,9 @@ func TestDNSProtocol(t *testing.T) {
                module := config.Module{
                        Timeout: time.Second,
                        DNS: config.DNSProbe{
-                               QueryName:           "example.com",
-                               TransportProtocol:   protocol,
-                               PreferredIPProtocol: "ip4",
+                               QueryName:         "example.com",
+                               TransportProtocol: protocol,
+                               IPProtocol:        "ip4",
                        },
                }
                registry := prometheus.NewRegistry()
@@ -424,9 +424,9 @@ func TestDNSProtocol(t *testing.T) {
                module = config.Module{
                        Timeout: time.Second,
                        DNS: config.DNSProbe{
-                               QueryName:           "example.com",
-                               TransportProtocol:   protocol,
-                               PreferredIPProtocol: "ip6",
+                               QueryName:         "example.com",
+                               TransportProtocol: protocol,
+                               IPProtocol:        "ip6",
                        },
                }
                registry = prometheus.NewRegistry()
@@ -449,9 +449,9 @@ func TestDNSProtocol(t *testing.T) {
                module = config.Module{
                        Timeout: time.Second,
                        DNS: config.DNSProbe{
-                               QueryName:           "example.com",
-                               TransportProtocol:   protocol,
-                               PreferredIPProtocol: "ip6",
+                               QueryName:         "example.com",
+                               TransportProtocol: protocol,
+                               IPProtocol:        "ip6",
                        },
                }
                registry = prometheus.NewRegistry()
@@ -474,9 +474,9 @@ func TestDNSProtocol(t *testing.T) {
                module = config.Module{
                        Timeout: time.Second,
                        DNS: config.DNSProbe{
-                               QueryName:           "example.com",
-                               TransportProtocol:   protocol,
-                               PreferredIPProtocol: "ip4",
+                               QueryName:         "example.com",
+                               TransportProtocol: protocol,
+                               IPProtocol:        "ip4",
                        },
                }
                registry = prometheus.NewRegistry()
index 71d1dec83f36a4664a6cf8d2843084d4efc0454b..542f3129b2345c6d732e86d4a5435eaa0da70aec 100644 (file)
@@ -203,7 +203,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr
                targetHost = targetURL.Host
        }
 
-       ip, lookupTime, err := chooseProtocol(module.HTTP.PreferredIPProtocol, targetHost, registry, logger)
+       ip, lookupTime, err := chooseProtocol(module.HTTP.IPProtocol, module.HTTP.IPProtocolFallback, targetHost, registry, logger)
        if err != nil {
                level.Error(logger).Log("msg", "Error resolving address", "err", err)
                return false
index 60b427139a908ecd0b853926ae30540da97f3c63..a7deaa89433ac46756b97c844a1498fbe73248cc 100644 (file)
@@ -59,7 +59,7 @@ func TestHTTPStatusCodes(t *testing.T) {
                testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
                defer cancel()
                result := ProbeHTTP(testCTX, ts.URL,
-                       config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{ValidStatusCodes: test.ValidStatusCodes}}, registry, log.NewNopLogger())
+                       config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, ValidStatusCodes: test.ValidStatusCodes}}, registry, log.NewNopLogger())
                body := recorder.Body.String()
                if result != test.ShouldSucceed {
                        t.Fatalf("Test %d had unexpected result: %s", i, body)
@@ -85,7 +85,8 @@ func TestValidHTTPVersion(t *testing.T) {
                registry := prometheus.NewRegistry()
                result := ProbeHTTP(context.Background(), ts.URL,
                        config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
-                               ValidHTTPVersions: test.ValidHTTPVersions,
+                               IPProtocolFallback: true,
+                               ValidHTTPVersions:  test.ValidHTTPVersions,
                        }}, registry, log.NewNopLogger())
                body := recorder.Body.String()
                if result != test.ShouldSucceed {
@@ -107,7 +108,7 @@ func TestRedirectFollowed(t *testing.T) {
        registry := prometheus.NewRegistry()
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
-       result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{}}, registry, log.NewNopLogger())
+       result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if !result {
                t.Fatalf("Redirect test failed unexpectedly, got %s", body)
@@ -135,7 +136,7 @@ func TestRedirectNotFollowed(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{NoFollowRedirects: true, ValidStatusCodes: []int{302}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, NoFollowRedirects: true, ValidStatusCodes: []int{302}}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if !result {
                t.Fatalf("Redirect test failed unexpectedly, got %s", body)
@@ -156,7 +157,7 @@ func TestPost(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{Method: "POST"}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, Method: "POST"}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if !result {
                t.Fatalf("Post test failed unexpectedly, got %s", body)
@@ -174,6 +175,7 @@ func TestBasicAuth(t *testing.T) {
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
                config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false},
                                BasicAuth: &pconfig.BasicAuth{Username: "username", Password: "password"},
@@ -196,6 +198,7 @@ func TestBearerToken(t *testing.T) {
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
                config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                BearerToken: pconfig.Secret("mysecret"),
                        },
@@ -216,7 +219,7 @@ func TestFailIfNotSSL(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotSSL: true}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfNotSSL: true}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if result {
                t.Fatalf("Fail if not SSL test suceeded unexpectedly, got %s", body)
@@ -242,7 +245,7 @@ func TestFailIfMatchesRegexp(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if result {
                t.Fatalf("Regexp test succeeded unexpectedly, got %s", body)
@@ -264,7 +267,7 @@ func TestFailIfMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if !result {
                t.Fatalf("Regexp test failed unexpectedly, got %s", body)
@@ -288,7 +291,7 @@ func TestFailIfMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if result {
                t.Fatalf("Regexp test succeeded unexpectedly, got %s", body)
@@ -302,7 +305,7 @@ func TestFailIfMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if !result {
                t.Fatalf("Regexp test failed unexpectedly, got %s", body)
@@ -320,7 +323,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if result {
                t.Fatalf("Regexp test succeeded unexpectedly, got %s", body)
@@ -334,7 +337,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if !result {
                t.Fatalf("Regexp test failed unexpectedly, got %s", body)
@@ -350,7 +353,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if result {
                t.Fatalf("Regexp test succeeded unexpectedly, got %s", body)
@@ -364,7 +367,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) {
        recorder = httptest.NewRecorder()
        registry = prometheus.NewRegistry()
        result = ProbeHTTP(testCTX, ts.URL,
-               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger())
+               config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger())
        body = recorder.Body.String()
        if !result {
                t.Fatalf("Regexp test failed unexpectedly, got %s", body)
@@ -396,7 +399,7 @@ func TestHTTPHeaders(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
-               Headers: headers,
+               Headers: headers, IPProtocolFallback: true,
        }}, registry, log.NewNopLogger())
        if !result {
                t.Fatalf("Probe failed unexpectedly.")
@@ -414,6 +417,7 @@ func TestFailIfSelfSignedCA(t *testing.T) {
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
                config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false},
                        },
@@ -443,6 +447,7 @@ func TestSucceedIfSelfSignedCA(t *testing.T) {
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
                config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: true},
                        },
@@ -472,6 +477,7 @@ func TestTLSConfigIsIgnoredForPlainHTTP(t *testing.T) {
        defer cancel()
        result := ProbeHTTP(testCTX, ts.URL,
                config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false},
                        },
@@ -525,7 +531,8 @@ func TestHTTPUsesTargetAsTLSServerName(t *testing.T) {
        module := config.Module{
                Timeout: time.Second,
                HTTP: config.HTTPProbe{
-                       PreferredIPProtocol: "ip4",
+                       IPProtocol:         "ip4",
+                       IPProtocolFallback: true,
                        HTTPClientConfig: pconfig.HTTPClientConfig{
                                TLSConfig: pconfig.TLSConfig{
                                        CAFile: tmpCaFile.Name(),
@@ -556,6 +563,7 @@ func TestHTTPPhases(t *testing.T) {
        defer cancel()
 
        result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{
+               IPProtocolFallback: true,
                HTTPClientConfig: pconfig.HTTPClientConfig{
                        TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: true},
                },
@@ -632,7 +640,7 @@ func TestCookieJar(t *testing.T) {
        registry := prometheus.NewRegistry()
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
-       result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{}}, registry, log.NewNopLogger())
+       result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true}}, registry, log.NewNopLogger())
        body := recorder.Body.String()
        if !result {
                t.Fatalf("Redirect test failed unexpectedly, got %s", body)
index 78bf6c2cf5927391fc26753841c835ef541a88a4..2e0126570b386589067f1fbe704390ee1a78cb7a 100644 (file)
@@ -64,7 +64,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
        timeoutDeadline, _ := ctx.Deadline()
        deadline := time.Now().Add(timeoutDeadline.Sub(time.Now()))
 
-       ip, lookupTime, err := chooseProtocol(module.ICMP.PreferredIPProtocol, target, registry, logger)
+       ip, lookupTime, err := chooseProtocol(module.ICMP.IPProtocol, module.ICMP.IPProtocolFallback, target, registry, logger)
        if err != nil {
                level.Warn(logger).Log("msg", "Error resolving address", "err", err)
                return false
index 48b5cb08132bc5d2e0ac118fa668b1ea213a6963..5bc13db5c418413888393037f9d3b5b0ac92588f 100644 (file)
@@ -38,7 +38,7 @@ func dialTCP(ctx context.Context, target string, module config.Module, registry
                return nil, err
        }
 
-       ip, _, err := chooseProtocol(module.TCP.PreferredIPProtocol, targetAddress, registry, logger)
+       ip, _, err := chooseProtocol(module.TCP.IPProtocol, module.TCP.IPProtocolFallback, targetAddress, registry, logger)
        if err != nil {
                level.Error(logger).Log("msg", "Error resolving address", "err", err)
                return nil, err
index d1afe060d234f5acedbb62d58de5d91f42c6de37..0e3709c161bb6556c92bbc88379bb6d873f727e1 100644 (file)
@@ -51,7 +51,7 @@ func TestTCPConnection(t *testing.T) {
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        registry := prometheus.NewRegistry()
-       if !ProbeTCP(testCTX, ln.Addr().String(), config.Module{}, registry, log.NewNopLogger()) {
+       if !ProbeTCP(testCTX, ln.Addr().String(), config.Module{TCP: config.TCPProbe{IPProtocolFallback: true}}, registry, log.NewNopLogger()) {
                t.Fatalf("TCP module failed, expected success.")
        }
        <-ch
@@ -62,7 +62,7 @@ func TestTCPConnectionFails(t *testing.T) {
        registry := prometheus.NewRegistry()
        testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
-       if ProbeTCP(testCTX, ":0", config.Module{}, registry, log.NewNopLogger()) {
+       if ProbeTCP(testCTX, ":0", config.Module{TCP: config.TCPProbe{IPProtocolFallback: true}}, registry, log.NewNopLogger()) {
                t.Fatalf("TCP module suceeded, expected failure.")
        }
 }
@@ -129,8 +129,9 @@ func TestTCPConnectionWithTLS(t *testing.T) {
        // Expect name-verified TLS connection.
        module := config.Module{
                TCP: config.TCPProbe{
-                       PreferredIPProtocol: "ipv4",
-                       TLS:                 true,
+                       IPProtocol:         "ipv4",
+                       IPProtocolFallback: true,
+                       TLS:                true,
                        TLSConfig: pconfig.TLSConfig{
                                CAFile:             tmpCaFile.Name(),
                                InsecureSkipVerify: false,
@@ -205,6 +206,7 @@ func TestTCPConnectionQueryResponseStartTLS(t *testing.T) {
        // Define some (bogus) example SMTP dialog with STARTTLS.
        module := config.Module{
                TCP: config.TCPProbe{
+                       IPProtocolFallback: true,
                        QueryResponse: []config.QueryResponse{
                                {Expect: "^220.*ESMTP.*$"},
                                {Send: "EHLO tls.prober"},
@@ -299,6 +301,7 @@ func TestTCPConnectionQueryResponseIRC(t *testing.T) {
 
        module := config.Module{
                TCP: config.TCPProbe{
+                       IPProtocolFallback: true,
                        QueryResponse: []config.QueryResponse{
                                {Send: "NICK prober"},
                                {Send: "USER prober prober prober :prober"},
@@ -367,6 +370,7 @@ func TestTCPConnectionQueryResponseMatching(t *testing.T) {
        time.Sleep(time.Millisecond * 100)
        module := config.Module{
                TCP: config.TCPProbe{
+                       IPProtocolFallback: true,
                        QueryResponse: []config.QueryResponse{
                                {
                                        Expect: "SSH-2.0-(OpenSSH_6.9p1) Debian-2",
@@ -433,7 +437,8 @@ func TestTCPConnectionProtocol(t *testing.T) {
        // Force IPv4
        module := config.Module{
                TCP: config.TCPProbe{
-                       PreferredIPProtocol: "ip4",
+                       IPProtocol:         "ip4",
+                       IPProtocolFallback: true,
                },
        }
 
@@ -473,7 +478,7 @@ func TestTCPConnectionProtocol(t *testing.T) {
        // Prefer IPv4
        module = config.Module{
                TCP: config.TCPProbe{
-                       PreferredIPProtocol: "ip4",
+                       IPProtocol: "ip4",
                },
        }
 
@@ -494,7 +499,8 @@ func TestTCPConnectionProtocol(t *testing.T) {
        // Prefer IPv6
        module = config.Module{
                TCP: config.TCPProbe{
-                       PreferredIPProtocol: "ip6",
+                       IPProtocol:         "ip6",
+                       IPProtocolFallback: true,
                },
        }
 
@@ -571,6 +577,7 @@ func TestPrometheusTimeoutTCP(t *testing.T) {
        defer cancel()
        registry := prometheus.NewRegistry()
        if ProbeTCP(testCTX, ln.Addr().String(), config.Module{TCP: config.TCPProbe{
+               IPProtocolFallback: true,
                QueryResponse: []config.QueryResponse{
                        {
                                Expect: "SSH-2.0-(OpenSSH_6.9p1) Debian-2",
index a2228a976a3fac529a181a203a0767aabde2a8dc..323868b01f889ca8374ca960467d7312be4a935b 100644 (file)
@@ -10,8 +10,8 @@ import (
        "github.com/prometheus/client_golang/prometheus"
 )
 
-// Returns the IP for the preferedIPProtocol and lookup time.
-func chooseProtocol(preferredIPProtocol string, target string, registry *prometheus.Registry, logger log.Logger) (ip *net.IPAddr, lookupTime float64, err error) {
+// Returns the IP for the IPProtocol and lookup time.
+func chooseProtocol(IPProtocol string, fallbackIPProtocol bool, target string, registry *prometheus.Registry, logger log.Logger) (ip *net.IPAddr, lookupTime float64, err error) {
        var fallbackProtocol string
        probeDNSLookupTimeSeconds := prometheus.NewGauge(prometheus.GaugeOpts{
                Name: "probe_dns_lookup_time_seconds",
@@ -25,21 +25,21 @@ func chooseProtocol(preferredIPProtocol string, target string, registry *prometh
        registry.MustRegister(probeIPProtocolGauge)
        registry.MustRegister(probeDNSLookupTimeSeconds)
 
-       if preferredIPProtocol == "ip6" || preferredIPProtocol == "" {
-               preferredIPProtocol = "ip6"
+       if IPProtocol == "ip6" || IPProtocol == "" {
+               IPProtocol = "ip6"
                fallbackProtocol = "ip4"
        } else {
-               preferredIPProtocol = "ip4"
+               IPProtocol = "ip4"
                fallbackProtocol = "ip6"
        }
 
-       if preferredIPProtocol == "ip6" {
+       if IPProtocol == "ip6" {
                fallbackProtocol = "ip4"
        } else {
                fallbackProtocol = "ip6"
        }
 
-       level.Info(logger).Log("msg", "Resolving target address", "preferred_ip_protocol", preferredIPProtocol)
+       level.Info(logger).Log("msg", "Resolving target address", "ip_protocol", IPProtocol)
        resolveStart := time.Now()
 
        defer func() {
@@ -47,10 +47,15 @@ func chooseProtocol(preferredIPProtocol string, target string, registry *prometh
                probeDNSLookupTimeSeconds.Add(lookupTime)
        }()
 
-       ip, err = net.ResolveIPAddr(preferredIPProtocol, target)
+       ip, err = net.ResolveIPAddr(IPProtocol, target)
        if err != nil {
-               level.Warn(logger).Log("msg", "Resolution with preferred IP protocol failed, attempting fallback protocol", "fallback_protocol", fallbackProtocol, "err", err)
-               ip, err = net.ResolveIPAddr(fallbackProtocol, target)
+               if fallbackIPProtocol == false {
+                       level.Error(logger).Log("msg", "Resolution with IP protocol failed (fallback_ip_protocol is false): err", err)
+               } else {
+                       level.Warn(logger).Log("msg", "Resolution with IP protocol failed, attempting fallback protocol", "fallback_protocol", fallbackProtocol, "err", err)
+                       ip, err = net.ResolveIPAddr(fallbackProtocol, target)
+               }
+
                if err != nil {
                        return ip, 0.0, err
                }