// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package cloudplugin import ( "bytes" "context" "errors" "io" "net/http" "net/http/httptest" "net/url" "testing" "time" ) func newHTTPTestServerUnsupported(t *testing.T) (*httptest.Server, error) { t.Helper() return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) w.Write([]byte("404 Not Found")) })), nil } func TestCloudPluginClient_DownloadFile(t *testing.T) { server, err := newCloudPluginManifestHTTPTestServer(t) if err != nil { t.Fatalf("could not create test server: %s", err) } defer server.Close() serverURL, _ := url.Parse(server.URL) serviceURL := serverURL.JoinPath("/api/cloudplugin/v1") client, err := NewCloudPluginClient(context.Background(), serviceURL) if err != nil { t.Fatalf("could not create test client: %s", err) } t.Run("200 response", func(t *testing.T) { buffer := bytes.Buffer{} err := client.DownloadFile("/archives/terraform-cloudplugin_0.1.0_SHA256SUMS", &buffer) if err != nil { t.Fatal("expected no error") } if buffer.Len() == 0 { t.Error("expected data, but got none") } }) t.Run("404 response", func(t *testing.T) { err := client.DownloadFile("/archives/nope.zip", io.Discard) if !errors.Is(err, ErrCloudPluginNotFound) { t.Fatalf("expected error %q, got %q", ErrCloudPluginNotFound, err) } }) } func TestCloudPluginClient_FetchManifest(t *testing.T) { server, err := newCloudPluginManifestHTTPTestServer(t) if err != nil { t.Fatalf("could not create test server: %s", err) } defer server.Close() serverURL, _ := url.Parse(server.URL) serviceURL := serverURL.JoinPath("/api/cloudplugin/v1") client, err := NewCloudPluginClient(context.Background(), serviceURL) if err != nil { t.Fatalf("could not create test client: %s", err) } t.Run("200 response", func(t *testing.T) { manifest, err := client.FetchManifest(time.Time{}) if err != nil { t.Fatal("expected no error") } if manifest == nil { t.Fatal("expected manifest") } if expected := "0.1.0"; manifest.Version != expected { t.Errorf("expected ProductVersion %q, got %q", expected, manifest.Version) } }) t.Run("304 response", func(t *testing.T) { manifest, err := client.FetchManifest(testManifestLastModified) if err != nil { t.Fatal("expected no error") } if manifest != nil { t.Fatalf("expected nil manifest, got %#v", manifest) } }) } func TestCloudPluginClient_NotSupportedByTerraformCloud(t *testing.T) { server, err := newHTTPTestServerUnsupported(t) if err != nil { t.Fatalf("could not create test server: %s", err) } defer server.Close() serverURL, _ := url.Parse(server.URL) serviceURL := serverURL.JoinPath("/api/cloudplugin/v1") client, err := NewCloudPluginClient(context.Background(), serviceURL) if err != nil { t.Fatalf("could not create test client: %s", err) } _, err = client.FetchManifest(time.Time{}) if !errors.Is(err, ErrCloudPluginNotSupported) { t.Errorf("Expected ErrCloudPluginNotSupported, got %v", err) } } func TestRelease_PrimarySHASumsSignatureURL(t *testing.T) { example := Release{ URLSHASumsSignatures: []string{ "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.sig", "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS/72D7468F.sig", // Not quite right "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.72D7468F.sig", }, } url, err := example.PrimarySHASumsSignatureURL() if err != nil { t.Fatalf("Expected no error, got %s", err) } if url != example.URLSHASumsSignatures[2] { t.Errorf("Expected URL %q, but got %q", example.URLSHASumsSignatures[2], url) } } func TestRelease_PrimarySHASumsSignatureURL_lowercase_should_match(t *testing.T) { example := Release{ URLSHASumsSignatures: []string{ "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.sig", "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.72d7468f.sig", }, } url, err := example.PrimarySHASumsSignatureURL() if err != nil { t.Fatalf("Expected no error, got %s", err) } // Not expected but technically fine since these are hex values if url != example.URLSHASumsSignatures[1] { t.Errorf("Expected URL %q, but got %q", example.URLSHASumsSignatures[1], url) } } func TestRelease_PrimarySHASumsSignatureURL_no_known_keys(t *testing.T) { example := Release{ URLSHASumsSignatures: []string{ "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.sig", "https://releases.hashicorp.com/terraform-cloudplugin/0.1.0-prototype/terraform-cloudplugin_0.1.0-prototype_SHA256SUMS.ABCDEF012.sig", }, } url, err := example.PrimarySHASumsSignatureURL() if err != nil { t.Fatalf("Expected no error, got %s", err) } // Returns key with no ID if url != example.URLSHASumsSignatures[0] { t.Errorf("Expected URL %q, but got %q", example.URLSHASumsSignatures[0], url) } }