github.com/rvichery/terraform@v0.11.10/state/remote/http_test.go (about)

     1  package remote
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"reflect"
    11  	"testing"
    12  
    13  	"github.com/hashicorp/go-cleanhttp"
    14  )
    15  
    16  func TestHTTPClient_impl(t *testing.T) {
    17  	var _ Client = new(HTTPClient)
    18  	var _ ClientLocker = new(HTTPClient)
    19  }
    20  
    21  func TestHTTPClient(t *testing.T) {
    22  	handler := new(testHTTPHandler)
    23  	ts := httptest.NewServer(http.HandlerFunc(handler.Handle))
    24  	defer ts.Close()
    25  
    26  	url, err := url.Parse(ts.URL)
    27  	if err != nil {
    28  		t.Fatalf("err: %s", err)
    29  	}
    30  
    31  	// Test basic get/update
    32  	client := &HTTPClient{URL: url, Client: cleanhttp.DefaultClient()}
    33  	testClient(t, client)
    34  
    35  	// test just a single PUT
    36  	p := &HTTPClient{
    37  		URL:          url,
    38  		UpdateMethod: "PUT",
    39  		Client:       cleanhttp.DefaultClient(),
    40  	}
    41  	testClient(t, p)
    42  
    43  	// Test locking and alternative UpdateMethod
    44  	a := &HTTPClient{
    45  		URL:          url,
    46  		UpdateMethod: "PUT",
    47  		LockURL:      url,
    48  		LockMethod:   "LOCK",
    49  		UnlockURL:    url,
    50  		UnlockMethod: "UNLOCK",
    51  		Client:       cleanhttp.DefaultClient(),
    52  	}
    53  	b := &HTTPClient{
    54  		URL:          url,
    55  		UpdateMethod: "PUT",
    56  		LockURL:      url,
    57  		LockMethod:   "LOCK",
    58  		UnlockURL:    url,
    59  		UnlockMethod: "UNLOCK",
    60  		Client:       cleanhttp.DefaultClient(),
    61  	}
    62  	TestRemoteLocks(t, a, b)
    63  
    64  	// test a WebDAV-ish backend
    65  	davhandler := new(testHTTPHandler)
    66  	ts = httptest.NewServer(http.HandlerFunc(davhandler.HandleWebDAV))
    67  	defer ts.Close()
    68  
    69  	url, err = url.Parse(ts.URL)
    70  	c := &HTTPClient{
    71  		URL:          url,
    72  		UpdateMethod: "PUT",
    73  		Client:       cleanhttp.DefaultClient(),
    74  	}
    75  	testClient(t, c) // first time through: 201
    76  	testClient(t, c) // second time, with identical data: 204
    77  }
    78  
    79  func assertError(t *testing.T, err error, expected string) {
    80  	if err == nil {
    81  		t.Fatalf("Expected empty config to err")
    82  	} else if err.Error() != expected {
    83  		t.Fatalf("Expected err.Error() to be \"%s\", got \"%s\"", expected, err.Error())
    84  	}
    85  }
    86  
    87  func TestHTTPClientFactory(t *testing.T) {
    88  	// missing address
    89  	_, err := httpFactory(map[string]string{})
    90  	assertError(t, err, "missing 'address' configuration")
    91  
    92  	// defaults
    93  	conf := map[string]string{
    94  		"address": "http://127.0.0.1:8888/foo",
    95  	}
    96  	c, err := httpFactory(conf)
    97  	client, _ := c.(*HTTPClient)
    98  	if client == nil || err != nil {
    99  		t.Fatal("Unexpected failure, address")
   100  	}
   101  	if client.URL.String() != conf["address"] {
   102  		t.Fatalf("Expected address \"%s\", got \"%s\"", conf["address"], client.URL.String())
   103  	}
   104  	if client.UpdateMethod != "POST" {
   105  		t.Fatalf("Expected update_method \"%s\", got \"%s\"", "POST", client.UpdateMethod)
   106  	}
   107  	if client.LockURL != nil || client.LockMethod != "LOCK" {
   108  		t.Fatal("Unexpected lock_address or lock_method")
   109  	}
   110  	if client.UnlockURL != nil || client.UnlockMethod != "UNLOCK" {
   111  		t.Fatal("Unexpected unlock_address or unlock_method")
   112  	}
   113  	if client.Username != "" || client.Password != "" {
   114  		t.Fatal("Unexpected username or password")
   115  	}
   116  
   117  	// custom
   118  	conf = map[string]string{
   119  		"address":        "http://127.0.0.1:8888/foo",
   120  		"update_method":  "BLAH",
   121  		"lock_address":   "http://127.0.0.1:8888/bar",
   122  		"lock_method":    "BLIP",
   123  		"unlock_address": "http://127.0.0.1:8888/baz",
   124  		"unlock_method":  "BLOOP",
   125  		"username":       "user",
   126  		"password":       "pass",
   127  	}
   128  	c, err = httpFactory(conf)
   129  	client, _ = c.(*HTTPClient)
   130  	if client == nil || err != nil {
   131  		t.Fatal("Unexpected failure, update_method")
   132  	}
   133  	if client.UpdateMethod != "BLAH" {
   134  		t.Fatalf("Expected update_method \"%s\", got \"%s\"", "BLAH", client.UpdateMethod)
   135  	}
   136  	if client.LockURL.String() != conf["lock_address"] || client.LockMethod != "BLIP" {
   137  		t.Fatalf("Unexpected lock_address \"%s\" vs \"%s\" or lock_method \"%s\" vs \"%s\"", client.LockURL.String(),
   138  			conf["lock_address"], client.LockMethod, conf["lock_method"])
   139  	}
   140  	if client.UnlockURL.String() != conf["unlock_address"] || client.UnlockMethod != "BLOOP" {
   141  		t.Fatalf("Unexpected unlock_address \"%s\" vs \"%s\" or unlock_method \"%s\" vs \"%s\"", client.UnlockURL.String(),
   142  			conf["unlock_address"], client.UnlockMethod, conf["unlock_method"])
   143  	}
   144  	if client.Username != "user" || client.Password != "pass" {
   145  		t.Fatalf("Unexpected username \"%s\" vs \"%s\" or password \"%s\" vs \"%s\"", client.Username, conf["username"],
   146  			client.Password, conf["password"])
   147  	}
   148  }
   149  
   150  type testHTTPHandler struct {
   151  	Data   []byte
   152  	Locked bool
   153  }
   154  
   155  func (h *testHTTPHandler) Handle(w http.ResponseWriter, r *http.Request) {
   156  	switch r.Method {
   157  	case "GET":
   158  		w.Write(h.Data)
   159  	case "PUT":
   160  		buf := new(bytes.Buffer)
   161  		if _, err := io.Copy(buf, r.Body); err != nil {
   162  			w.WriteHeader(500)
   163  		}
   164  		w.WriteHeader(201)
   165  		h.Data = buf.Bytes()
   166  	case "POST":
   167  		buf := new(bytes.Buffer)
   168  		if _, err := io.Copy(buf, r.Body); err != nil {
   169  			w.WriteHeader(500)
   170  		}
   171  		h.Data = buf.Bytes()
   172  	case "LOCK":
   173  		if h.Locked {
   174  			w.WriteHeader(423)
   175  		} else {
   176  			h.Locked = true
   177  		}
   178  	case "UNLOCK":
   179  		h.Locked = false
   180  	case "DELETE":
   181  		h.Data = nil
   182  		w.WriteHeader(200)
   183  	default:
   184  		w.WriteHeader(500)
   185  		w.Write([]byte(fmt.Sprintf("Unknown method: %s", r.Method)))
   186  	}
   187  }
   188  
   189  // mod_dav-ish behavior
   190  func (h *testHTTPHandler) HandleWebDAV(w http.ResponseWriter, r *http.Request) {
   191  	switch r.Method {
   192  	case "GET":
   193  		w.Write(h.Data)
   194  	case "PUT":
   195  		buf := new(bytes.Buffer)
   196  		if _, err := io.Copy(buf, r.Body); err != nil {
   197  			w.WriteHeader(500)
   198  		}
   199  		if reflect.DeepEqual(h.Data, buf.Bytes()) {
   200  			h.Data = buf.Bytes()
   201  			w.WriteHeader(204)
   202  		} else {
   203  			h.Data = buf.Bytes()
   204  			w.WriteHeader(201)
   205  		}
   206  	case "DELETE":
   207  		h.Data = nil
   208  		w.WriteHeader(200)
   209  	default:
   210  		w.WriteHeader(500)
   211  		w.Write([]byte(fmt.Sprintf("Unknown method: %s", r.Method)))
   212  	}
   213  }