github.com/jhixson74/hashicorp-terraform@v0.11.12-beta1/plugin/discovery/get_test.go (about) 1 package discovery 2 3 import ( 4 "archive/zip" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "os" 11 "path/filepath" 12 "reflect" 13 "regexp" 14 "strings" 15 "testing" 16 17 "github.com/mitchellh/cli" 18 ) 19 20 const testProviderFile = "test provider binary" 21 22 // return the directory listing for the "test" provider 23 func testListingHandler(w http.ResponseWriter, r *http.Request) { 24 w.Write([]byte(versionList)) 25 } 26 27 func testChecksumHandler(w http.ResponseWriter, r *http.Request) { 28 // this exact plugin has a signnature and checksum file 29 if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS" { 30 http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS") 31 return 32 } 33 if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig" { 34 http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig") 35 return 36 } 37 38 // this this checksum file is corrupt and doesn't match the sig 39 if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS" { 40 http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS") 41 return 42 } 43 if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS.sig" { 44 http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig") 45 return 46 } 47 48 http.Error(w, "signtaure files not found", http.StatusNotFound) 49 } 50 51 // returns a 200 for a valid provider url, using the patch number for the 52 // plugin protocol version. 53 func testHandler(w http.ResponseWriter, r *http.Request) { 54 if r.URL.Path == "/terraform-provider-test/" { 55 testListingHandler(w, r) 56 return 57 } 58 59 parts := strings.Split(r.URL.Path, "/") 60 if len(parts) != 4 { 61 http.Error(w, "not found", http.StatusNotFound) 62 return 63 } 64 65 filename := parts[3] 66 67 reg := regexp.MustCompile(`(terraform-provider-test)_(\d).(\d).(\d)_([^_]+)_([^._]+).zip`) 68 69 fileParts := reg.FindStringSubmatch(filename) 70 if len(fileParts) != 7 { 71 http.Error(w, "invalid provider: "+filename, http.StatusNotFound) 72 return 73 } 74 75 w.Header().Set(protocolVersionHeader, fileParts[4]) 76 77 // write a dummy file 78 z := zip.NewWriter(w) 79 fn := fmt.Sprintf("%s_v%s.%s.%s_x%s", fileParts[1], fileParts[2], fileParts[3], fileParts[4], fileParts[4]) 80 f, err := z.Create(fn) 81 if err != nil { 82 panic(err) 83 } 84 io.WriteString(f, testProviderFile) 85 z.Close() 86 } 87 88 func testReleaseServer() *httptest.Server { 89 handler := http.NewServeMux() 90 handler.HandleFunc("/terraform-provider-test/", testHandler) 91 handler.HandleFunc("/terraform-provider-template/", testChecksumHandler) 92 handler.HandleFunc("/terraform-provider-badsig/", testChecksumHandler) 93 94 return httptest.NewServer(handler) 95 } 96 97 func TestMain(m *testing.M) { 98 server := testReleaseServer() 99 releaseHost = server.URL 100 101 os.Exit(m.Run()) 102 } 103 104 func TestVersionListing(t *testing.T) { 105 i := &ProviderInstaller{} 106 versions, err := i.listProviderVersions("test") 107 if err != nil { 108 t.Fatal(err) 109 } 110 111 Versions(versions).Sort() 112 113 expected := []string{ 114 "1.2.4", 115 "1.2.3", 116 "1.2.1", 117 } 118 119 if len(versions) != len(expected) { 120 t.Fatalf("Received wrong number of versions. expected: %q, got: %q", expected, versions) 121 } 122 123 for i, v := range versions { 124 if v.String() != expected[i] { 125 t.Fatalf("incorrect version: %q, expected %q", v, expected[i]) 126 } 127 } 128 } 129 130 func TestCheckProtocolVersions(t *testing.T) { 131 i := &ProviderInstaller{} 132 if checkPlugin(i.providerURL("test", VersionStr("1.2.3").MustParse().String()), 4) { 133 t.Fatal("protocol version 4 is not compatible") 134 } 135 136 if !checkPlugin(i.providerURL("test", VersionStr("1.2.3").MustParse().String()), 3) { 137 t.Fatal("protocol version 3 should be compatible") 138 } 139 } 140 141 func TestProviderInstallerGet(t *testing.T) { 142 tmpDir, err := ioutil.TempDir("", "tf-plugin") 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 defer os.RemoveAll(tmpDir) 148 149 // attempt to use an incompatible protocol version 150 i := &ProviderInstaller{ 151 Dir: tmpDir, 152 PluginProtocolVersion: 5, 153 SkipVerify: true, 154 Ui: cli.NewMockUi(), 155 } 156 _, err = i.Get("test", AllVersions) 157 if err != ErrorNoVersionCompatible { 158 t.Fatal("want error for incompatible version") 159 } 160 161 i = &ProviderInstaller{ 162 Dir: tmpDir, 163 PluginProtocolVersion: 3, 164 SkipVerify: true, 165 Ui: cli.NewMockUi(), 166 } 167 168 { 169 _, err := i.Get("test", ConstraintStr(">9.0.0").MustParse()) 170 if err != ErrorNoSuitableVersion { 171 t.Fatal("want error for mismatching constraints") 172 } 173 } 174 175 { 176 _, err := i.Get("nonexist", AllVersions) 177 if err != ErrorNoSuchProvider { 178 t.Fatal("want error for no such provider") 179 } 180 } 181 182 gotMeta, err := i.Get("test", AllVersions) 183 if err != nil { 184 t.Fatal(err) 185 } 186 187 // we should have version 1.2.3 188 dest := filepath.Join(tmpDir, "terraform-provider-test_v1.2.3_x3") 189 190 wantMeta := PluginMeta{ 191 Name: "test", 192 Version: VersionStr("1.2.3"), 193 Path: dest, 194 } 195 if !reflect.DeepEqual(gotMeta, wantMeta) { 196 t.Errorf("wrong result meta\ngot: %#v\nwant: %#v", gotMeta, wantMeta) 197 } 198 199 f, err := ioutil.ReadFile(dest) 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 // provider should have been unzipped 205 if string(f) != testProviderFile { 206 t.Fatalf("test provider contains: %q", f) 207 } 208 209 } 210 211 func TestProviderInstallerPurgeUnused(t *testing.T) { 212 tmpDir, err := ioutil.TempDir("", "tf-plugin") 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 defer os.RemoveAll(tmpDir) 218 219 unwantedPath := filepath.Join(tmpDir, "terraform-provider-test_v0.0.1_x2") 220 wantedPath := filepath.Join(tmpDir, "terraform-provider-test_v1.2.3_x3") 221 222 f, err := os.Create(unwantedPath) 223 if err != nil { 224 t.Fatal(err) 225 } 226 f.Close() 227 f, err = os.Create(wantedPath) 228 if err != nil { 229 t.Fatal(err) 230 } 231 f.Close() 232 233 i := &ProviderInstaller{ 234 Dir: tmpDir, 235 PluginProtocolVersion: 3, 236 SkipVerify: true, 237 Ui: cli.NewMockUi(), 238 } 239 purged, err := i.PurgeUnused(map[string]PluginMeta{ 240 "test": PluginMeta{ 241 Name: "test", 242 Version: VersionStr("1.2.3"), 243 Path: wantedPath, 244 }, 245 }) 246 if err != nil { 247 t.Fatal(err) 248 } 249 250 if got, want := purged.Count(), 1; got != want { 251 t.Errorf("wrong purged count %d; want %d", got, want) 252 } 253 if got, want := purged.Newest().Path, unwantedPath; got != want { 254 t.Errorf("wrong purged path %s; want %s", got, want) 255 } 256 257 files, err := ioutil.ReadDir(tmpDir) 258 if err != nil { 259 t.Fatal(err) 260 } 261 262 gotFilenames := make([]string, len(files)) 263 for i, info := range files { 264 gotFilenames[i] = info.Name() 265 } 266 wantFilenames := []string{"terraform-provider-test_v1.2.3_x3"} 267 268 if !reflect.DeepEqual(gotFilenames, wantFilenames) { 269 t.Errorf("wrong filenames after purge\ngot: %#v\nwant: %#v", gotFilenames, wantFilenames) 270 } 271 } 272 273 // Test fetching a provider's checksum file while verifying its signature. 274 func TestProviderChecksum(t *testing.T) { 275 i := &ProviderInstaller{} 276 277 // we only need the checksum, as getter is doing the actual file comparison. 278 sha256sum, err := i.getProviderChecksum("template", "0.1.0") 279 if err != nil { 280 t.Fatal(err) 281 } 282 283 // get the expected checksum for our os/arch 284 sumData, err := ioutil.ReadFile("testdata/terraform-provider-template_0.1.0_SHA256SUMS") 285 if err != nil { 286 t.Fatal(err) 287 } 288 289 expected := checksumForFile(sumData, i.providerFileName("template", "0.1.0")) 290 291 if sha256sum != expected { 292 t.Fatalf("expected: %s\ngot %s\n", sha256sum, expected) 293 } 294 } 295 296 // Test fetching a provider's checksum file witha bad signature 297 func TestProviderChecksumBadSignature(t *testing.T) { 298 i := &ProviderInstaller{} 299 300 // we only need the checksum, as getter is doing the actual file comparison. 301 sha256sum, err := i.getProviderChecksum("badsig", "0.1.0") 302 if err == nil { 303 t.Fatal("expcted error") 304 } 305 306 if !strings.Contains(err.Error(), "signature") { 307 t.Fatal("expected signature error, got:", err) 308 } 309 310 if sha256sum != "" { 311 t.Fatal("expected no checksum, got:", sha256sum) 312 } 313 } 314 315 const versionList = `<!DOCTYPE html> 316 <html> 317 <body> 318 <ul> 319 <li> 320 <a href="../">../</a> 321 </li> 322 <li> 323 <a href="/terraform-provider-test/1.2.3/">terraform-provider-test_1.2.3</a> 324 </li> 325 <li> 326 <a href="/terraform-provider-test/1.2.1/">terraform-provider-test_1.2.1</a> 327 </li> 328 <li> 329 <a href="/terraform-provider-test/1.2.4/">terraform-provider-test_1.2.4</a> 330 </li> 331 </ul> 332 <footer> 333 Proudly fronted by <a href="https://fastly.com/?utm_source=hashicorp" target="_TOP">Fastly</a> 334 </footer> 335 </body> 336 </html> 337 `