...

Source file src/github.com/docker/distribution/registry/handlers/health_test.go

Documentation: github.com/docker/distribution/registry/handlers

     1  package handlers
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/docker/distribution/configuration"
    13  	"github.com/docker/distribution/context"
    14  	"github.com/docker/distribution/health"
    15  )
    16  
    17  func TestFileHealthCheck(t *testing.T) {
    18  	interval := time.Second
    19  
    20  	tmpfile, err := ioutil.TempFile(os.TempDir(), "healthcheck")
    21  	if err != nil {
    22  		t.Fatalf("could not create temporary file: %v", err)
    23  	}
    24  	defer tmpfile.Close()
    25  
    26  	config := &configuration.Configuration{
    27  		Storage: configuration.Storage{
    28  			"inmemory": configuration.Parameters{},
    29  			"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
    30  				"enabled": false,
    31  			}},
    32  		},
    33  		Health: configuration.Health{
    34  			FileCheckers: []configuration.FileChecker{
    35  				{
    36  					Interval: interval,
    37  					File:     tmpfile.Name(),
    38  				},
    39  			},
    40  		},
    41  	}
    42  
    43  	ctx := context.Background()
    44  
    45  	app := NewApp(ctx, config)
    46  	healthRegistry := health.NewRegistry()
    47  	app.RegisterHealthChecks(healthRegistry)
    48  
    49  	// Wait for health check to happen
    50  	<-time.After(2 * interval)
    51  
    52  	status := healthRegistry.CheckStatus()
    53  	if len(status) != 1 {
    54  		t.Fatal("expected 1 item in health check results")
    55  	}
    56  	if status[tmpfile.Name()] != "file exists" {
    57  		t.Fatal(`did not get "file exists" result for health check`)
    58  	}
    59  
    60  	os.Remove(tmpfile.Name())
    61  
    62  	<-time.After(2 * interval)
    63  	if len(healthRegistry.CheckStatus()) != 0 {
    64  		t.Fatal("expected 0 items in health check results")
    65  	}
    66  }
    67  
    68  func TestTCPHealthCheck(t *testing.T) {
    69  	interval := time.Second
    70  
    71  	ln, err := net.Listen("tcp", "127.0.0.1:0")
    72  	if err != nil {
    73  		t.Fatalf("could not create listener: %v", err)
    74  	}
    75  	addrStr := ln.Addr().String()
    76  
    77  	// Start accepting
    78  	go func() {
    79  		for {
    80  			conn, err := ln.Accept()
    81  			if err != nil {
    82  				// listener was closed
    83  				return
    84  			}
    85  			defer conn.Close()
    86  		}
    87  	}()
    88  
    89  	config := &configuration.Configuration{
    90  		Storage: configuration.Storage{
    91  			"inmemory": configuration.Parameters{},
    92  			"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
    93  				"enabled": false,
    94  			}},
    95  		},
    96  		Health: configuration.Health{
    97  			TCPCheckers: []configuration.TCPChecker{
    98  				{
    99  					Interval: interval,
   100  					Addr:     addrStr,
   101  					Timeout:  500 * time.Millisecond,
   102  				},
   103  			},
   104  		},
   105  	}
   106  
   107  	ctx := context.Background()
   108  
   109  	app := NewApp(ctx, config)
   110  	healthRegistry := health.NewRegistry()
   111  	app.RegisterHealthChecks(healthRegistry)
   112  
   113  	// Wait for health check to happen
   114  	<-time.After(2 * interval)
   115  
   116  	if len(healthRegistry.CheckStatus()) != 0 {
   117  		t.Fatal("expected 0 items in health check results")
   118  	}
   119  
   120  	ln.Close()
   121  	<-time.After(2 * interval)
   122  
   123  	// Health check should now fail
   124  	status := healthRegistry.CheckStatus()
   125  	if len(status) != 1 {
   126  		t.Fatal("expected 1 item in health check results")
   127  	}
   128  	if status[addrStr] != "connection to "+addrStr+" failed" {
   129  		t.Fatal(`did not get "connection failed" result for health check`)
   130  	}
   131  }
   132  
   133  func TestHTTPHealthCheck(t *testing.T) {
   134  	interval := time.Second
   135  	threshold := 3
   136  
   137  	stopFailing := make(chan struct{})
   138  
   139  	checkedServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   140  		if r.Method != "HEAD" {
   141  			t.Fatalf("expected HEAD request, got %s", r.Method)
   142  		}
   143  		select {
   144  		case <-stopFailing:
   145  			w.WriteHeader(http.StatusOK)
   146  		default:
   147  			w.WriteHeader(http.StatusInternalServerError)
   148  		}
   149  	}))
   150  
   151  	config := &configuration.Configuration{
   152  		Storage: configuration.Storage{
   153  			"inmemory": configuration.Parameters{},
   154  			"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
   155  				"enabled": false,
   156  			}},
   157  		},
   158  		Health: configuration.Health{
   159  			HTTPCheckers: []configuration.HTTPChecker{
   160  				{
   161  					Interval:  interval,
   162  					URI:       checkedServer.URL,
   163  					Threshold: threshold,
   164  				},
   165  			},
   166  		},
   167  	}
   168  
   169  	ctx := context.Background()
   170  
   171  	app := NewApp(ctx, config)
   172  	healthRegistry := health.NewRegistry()
   173  	app.RegisterHealthChecks(healthRegistry)
   174  
   175  	for i := 0; ; i++ {
   176  		<-time.After(interval)
   177  
   178  		status := healthRegistry.CheckStatus()
   179  
   180  		if i < threshold-1 {
   181  			// definitely shouldn't have hit the threshold yet
   182  			if len(status) != 0 {
   183  				t.Fatal("expected 1 item in health check results")
   184  			}
   185  			continue
   186  		}
   187  		if i < threshold+1 {
   188  			// right on the threshold - don't expect a failure yet
   189  			continue
   190  		}
   191  
   192  		if len(status) != 1 {
   193  			t.Fatal("expected 1 item in health check results")
   194  		}
   195  		if status[checkedServer.URL] != "downstream service returned unexpected status: 500" {
   196  			t.Fatal("did not get expected result for health check")
   197  		}
   198  
   199  		break
   200  	}
   201  
   202  	// Signal HTTP handler to start returning 200
   203  	close(stopFailing)
   204  
   205  	<-time.After(2 * interval)
   206  
   207  	if len(healthRegistry.CheckStatus()) != 0 {
   208  		t.Fatal("expected 0 items in health check results")
   209  	}
   210  }
   211  

View as plain text