github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/heroku/resource_heroku_cert_test.go (about)

     1  package heroku
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"regexp"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/cyberdelia/heroku-go/v3"
    14  	"github.com/hashicorp/terraform/helper/acctest"
    15  	"github.com/hashicorp/terraform/helper/resource"
    16  	"github.com/hashicorp/terraform/terraform"
    17  )
    18  
    19  // We break apart testing for EU and US because at present, Heroku deals with
    20  // each a bit differently and the setup/teardown of separate tests seems to
    21  // help them to perform more consistently.
    22  // https://devcenter.heroku.com/articles/ssl-endpoint#add-certificate-and-intermediaries
    23  //
    24  // We also have a time.Sleep() set for the update step (step 2 of 2) in each
    25  // region's tests. This is somewhat kludgy, but the Heroku API SSL Endpoint
    26  // handles parts of the create and update requests asynchronously, and if you
    27  // add a cert+key then immediately update it, and then delete it (end of test),
    28  // there are scenarios where the operations get out of order. For now, sleeping
    29  // on update seems to allow the test to run smoothly; in real life, this test
    30  // case is definitely an extreme edge case.
    31  func TestAccHerokuCert_EU(t *testing.T) {
    32  	var endpoint heroku.SSLEndpoint
    33  	appName := fmt.Sprintf("tftest-%s", acctest.RandString(10))
    34  
    35  	wd, _ := os.Getwd()
    36  	certFile := wd + "/test-fixtures/terraform.cert"
    37  	certFile2 := wd + "/test-fixtures/terraform2.cert"
    38  	keyFile := wd + "/test-fixtures/terraform.key"
    39  	keyFile2 := wd + "/test-fixtures/terraform2.key"
    40  
    41  	certificateChainBytes, _ := ioutil.ReadFile(certFile)
    42  	certificateChain := string(certificateChainBytes)
    43  	certificateChain2Bytes, _ := ioutil.ReadFile(certFile2)
    44  	certificateChain2 := string(certificateChain2Bytes)
    45  
    46  	resource.Test(t, resource.TestCase{
    47  		PreCheck:     func() { testAccPreCheck(t) },
    48  		Providers:    testAccProviders,
    49  		CheckDestroy: testAccCheckHerokuCertDestroy,
    50  		Steps: []resource.TestStep{
    51  			{
    52  				Config: testAccCheckHerokuCertEUConfig(appName, certFile, keyFile),
    53  				Check: resource.ComposeTestCheckFunc(
    54  					testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint),
    55  					testAccCheckHerokuCertificateChain(&endpoint, certificateChain),
    56  					resource.TestCheckResourceAttr(
    57  						"heroku_cert.ssl_certificate",
    58  						"cname", fmt.Sprintf("%s.herokuapp.com", appName)),
    59  				),
    60  			},
    61  			{
    62  				PreConfig: sleep(t, 15),
    63  				Config:    testAccCheckHerokuCertEUConfig(appName, certFile2, keyFile2),
    64  				Check: resource.ComposeTestCheckFunc(
    65  					testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint),
    66  					testAccCheckHerokuCertificateChain(&endpoint, certificateChain2),
    67  					resource.TestCheckResourceAttr(
    68  						"heroku_cert.ssl_certificate",
    69  						"cname", fmt.Sprintf("%s.herokuapp.com", appName)),
    70  				),
    71  			},
    72  		},
    73  	})
    74  }
    75  
    76  func TestAccHerokuCert_US(t *testing.T) {
    77  	var endpoint heroku.SSLEndpoint
    78  	appName := fmt.Sprintf("tftest-%s", acctest.RandString(10))
    79  
    80  	wd, _ := os.Getwd()
    81  	certFile := wd + "/test-fixtures/terraform.cert"
    82  	certFile2 := wd + "/test-fixtures/terraform2.cert"
    83  	keyFile := wd + "/test-fixtures/terraform.key"
    84  	keyFile2 := wd + "/test-fixtures/terraform2.key"
    85  
    86  	certificateChainBytes, _ := ioutil.ReadFile(certFile)
    87  	certificateChain := string(certificateChainBytes)
    88  	certificateChain2Bytes, _ := ioutil.ReadFile(certFile2)
    89  	certificateChain2 := string(certificateChain2Bytes)
    90  
    91  	resource.Test(t, resource.TestCase{
    92  		PreCheck:     func() { testAccPreCheck(t) },
    93  		Providers:    testAccProviders,
    94  		CheckDestroy: testAccCheckHerokuCertDestroy,
    95  		Steps: []resource.TestStep{
    96  			{
    97  				Config: testAccCheckHerokuCertUSConfig(appName, certFile2, keyFile2),
    98  				Check: resource.ComposeTestCheckFunc(
    99  					testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint),
   100  					testAccCheckHerokuCertificateChain(&endpoint, certificateChain2),
   101  					resource.TestMatchResourceAttr(
   102  						"heroku_cert.ssl_certificate",
   103  						"cname", regexp.MustCompile(`herokussl`)),
   104  				),
   105  			},
   106  			{
   107  				PreConfig: sleep(t, 15),
   108  				Config:    testAccCheckHerokuCertUSConfig(appName, certFile, keyFile),
   109  				Check: resource.ComposeTestCheckFunc(
   110  					testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint),
   111  					testAccCheckHerokuCertificateChain(&endpoint, certificateChain),
   112  					resource.TestMatchResourceAttr(
   113  						"heroku_cert.ssl_certificate",
   114  						"cname", regexp.MustCompile(`herokussl`)),
   115  				),
   116  			},
   117  		},
   118  	})
   119  }
   120  
   121  func testAccCheckHerokuCertEUConfig(appName, certFile, keyFile string) string {
   122  	return strings.TrimSpace(fmt.Sprintf(`
   123  resource "heroku_app" "foobar" {
   124    name = "%s"
   125    region = "eu"
   126  }
   127  
   128  resource "heroku_addon" "ssl" {
   129    app = "${heroku_app.foobar.name}"
   130    plan = "ssl:endpoint"
   131  }
   132  
   133  resource "heroku_cert" "ssl_certificate" {
   134    app = "${heroku_app.foobar.name}"
   135    depends_on = ["heroku_addon.ssl"]
   136    certificate_chain="${file("%s")}"
   137    private_key="${file("%s")}"
   138  }`, appName, certFile, keyFile))
   139  }
   140  
   141  func testAccCheckHerokuCertUSConfig(appName, certFile, keyFile string) string {
   142  	return strings.TrimSpace(fmt.Sprintf(`
   143  resource "heroku_app" "foobar" {
   144    name = "%s"
   145    region = "us"
   146  }
   147  
   148  resource "heroku_addon" "ssl" {
   149    app = "${heroku_app.foobar.name}"
   150    plan = "ssl:endpoint"
   151  }
   152  
   153  resource "heroku_cert" "ssl_certificate" {
   154    app = "${heroku_app.foobar.name}"
   155    depends_on = ["heroku_addon.ssl"]
   156    certificate_chain="${file("%s")}"
   157    private_key="${file("%s")}"
   158  }`, appName, certFile, keyFile))
   159  }
   160  
   161  func sleep(t *testing.T, amount time.Duration) func() {
   162  	return func() {
   163  		time.Sleep(amount * time.Second)
   164  	}
   165  }
   166  
   167  func testAccCheckHerokuCertDestroy(s *terraform.State) error {
   168  	client := testAccProvider.Meta().(*heroku.Service)
   169  
   170  	for _, rs := range s.RootModule().Resources {
   171  		if rs.Type != "heroku_cert" {
   172  			continue
   173  		}
   174  
   175  		_, err := client.SSLEndpointInfo(context.TODO(), rs.Primary.Attributes["app"], rs.Primary.ID)
   176  
   177  		if err == nil {
   178  			return fmt.Errorf("Cerfificate still exists")
   179  		}
   180  	}
   181  
   182  	return nil
   183  }
   184  
   185  func testAccCheckHerokuCertificateChain(endpoint *heroku.SSLEndpoint, chain string) resource.TestCheckFunc {
   186  	return func(s *terraform.State) error {
   187  
   188  		if endpoint.CertificateChain != chain {
   189  			return fmt.Errorf("Bad certificate chain: %s", endpoint.CertificateChain)
   190  		}
   191  
   192  		return nil
   193  	}
   194  }
   195  
   196  func testAccCheckHerokuCertExists(n string, endpoint *heroku.SSLEndpoint) resource.TestCheckFunc {
   197  	return func(s *terraform.State) error {
   198  		rs, ok := s.RootModule().Resources[n]
   199  
   200  		if !ok {
   201  			return fmt.Errorf("Not found: %s", n)
   202  		}
   203  
   204  		if rs.Primary.ID == "" {
   205  			return fmt.Errorf("No SSL endpoint ID is set")
   206  		}
   207  
   208  		client := testAccProvider.Meta().(*heroku.Service)
   209  
   210  		foundEndpoint, err := client.SSLEndpointInfo(context.TODO(), rs.Primary.Attributes["app"], rs.Primary.ID)
   211  
   212  		if err != nil {
   213  			return err
   214  		}
   215  
   216  		if foundEndpoint.ID != rs.Primary.ID {
   217  			return fmt.Errorf("SSL endpoint not found")
   218  		}
   219  
   220  		*endpoint = *foundEndpoint
   221  
   222  		return nil
   223  	}
   224  }