github.com/ctrox/terraform@v0.11.12-beta1/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 }