From 3fa2dffb86f215d9c996567d3d2c3540a975e93d Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Thu, 4 May 2017 19:16:17 -0400 Subject: [PATCH 1/9] Attempt to write a new test for cert update Trying to surface this bug with a test: https://github.com/hashicorp/terraform/issues/5930 --- .../heroku/resource_heroku_cert_test.go | 60 ++++++++++++------- .../heroku/test-fixtures/terraform2.key | 27 +++++++++ 2 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 builtin/providers/heroku/test-fixtures/terraform2.key diff --git a/builtin/providers/heroku/resource_heroku_cert_test.go b/builtin/providers/heroku/resource_heroku_cert_test.go index e40fe4b03cb0..31840887bd01 100644 --- a/builtin/providers/heroku/resource_heroku_cert_test.go +++ b/builtin/providers/heroku/resource_heroku_cert_test.go @@ -15,29 +15,15 @@ import ( func TestAccHerokuCert_Basic(t *testing.T) { var endpoint heroku.SSLEndpointInfoResult + appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) + wd, _ := os.Getwd() - certificateChainFile := wd + "/test-fixtures/terraform.cert" - certificateChainBytes, _ := ioutil.ReadFile(certificateChainFile) + certFile := wd + "/test-fixtures/terraform.cert" + keyFile := wd + "/test-fixtures/terraform.key" + keyFile2 := wd + "/test-fixtures/terraform2.key" + + certificateChainBytes, _ := ioutil.ReadFile(certFile) certificateChain := string(certificateChainBytes) - appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) - testAccCheckHerokuCertConfig_basic := ` - resource "heroku_app" "foobar" { - name = "` + appName + `" - region = "eu" - } - - resource "heroku_addon" "ssl" { - app = "${heroku_app.foobar.name}" - plan = "ssl:endpoint" - } - - resource "heroku_cert" "ssl_certificate" { - app = "${heroku_app.foobar.name}" - depends_on = ["heroku_addon.ssl"] - certificate_chain="${file("` + certificateChainFile + `")}" - private_key="${file("` + wd + `/test-fixtures/terraform.key")}" - } - ` resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -45,7 +31,17 @@ func TestAccHerokuCert_Basic(t *testing.T) { CheckDestroy: testAccCheckHerokuCertDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckHerokuCertConfig_basic, + Config: testAccCheckHerokuCertConfig(appName, certFile, keyFile), + Check: resource.ComposeTestCheckFunc( + testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), + testAccCheckHerokuCertificateChain(&endpoint, certificateChain), + resource.TestCheckResourceAttr( + "heroku_cert.ssl_certificate", + "cname", fmt.Sprintf("%s.herokuapp.com", appName)), + ), + }, + { + Config: testAccCheckHerokuCertConfig(appName, certFile, keyFile2), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), testAccCheckHerokuCertificateChain(&endpoint, certificateChain), @@ -58,6 +54,26 @@ func TestAccHerokuCert_Basic(t *testing.T) { }) } +func testAccCheckHerokuCertConfig(appName, certFile, keyFile string) string { + return fmt.Sprintf(` +resource "heroku_app" "foobar" { + name = "%s" + region = "us" +} + +resource "heroku_addon" "ssl" { + app = "${heroku_app.foobar.name}" + plan = "ssl:endpoint" +} + +resource "heroku_cert" "ssl_certificate" { + app = "${heroku_app.foobar.name}" + depends_on = ["heroku_addon.ssl"] + certificate_chain="${file("%s")}" + private_key="${file("%s")}" +}`, appName, certFile, keyFile) +} + func testAccCheckHerokuCertDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*heroku.Service) diff --git a/builtin/providers/heroku/test-fixtures/terraform2.key b/builtin/providers/heroku/test-fixtures/terraform2.key new file mode 100644 index 000000000000..378917eaa25a --- /dev/null +++ b/builtin/providers/heroku/test-fixtures/terraform2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAu7KeqCenM3UaZeWswe42iwsEN/Hqldk0RT1VYzw+3FsoVdkR +Bbane7xBfwFK6d/gAr3Opi3U4w7mhlVYGuKAONkIKs+Vs5Jd7ZwUgQ5cRV14PqeF +IyVmTy1IjjG7x1jRrYTvRtXaeYfa4ale8CYcgJU6pZ1e2mnklnCYGH4e8THudAZQ +JoessKZ55Wc7MuHiYicIG4JRvDlNCSvtTsXTlA3v9XlDoRTz8dVP6dubfGeqmiPB +Qyz8E1Wc67zmdL00EisngNGYQUx9RoVKq6KIA5TxE4JJ3umKr2aMZaPPvVnY5Z9m +42Hv50VmCkeQcQuOj5zSTDzyRSP1TSz2GpwLuQIDAQABAoIBAQCethLiLWV8ZXDE +6MiD02HbgJ04kR7DRr6kLZCeMLsWqR4aOUnjgudsAWuAcR9fUyagKs8qRWbV+CuF +O3UchpnVd+8oBA+ZoBI8cNYFqpbrMHYUxKIXbfBs0uWfFv6pOblS+C07wGjUisPS +PN1CQ3emYokMsV0bYp8fdmWlkD+pwhHH3vsPm4sYwbabaURRxZYLNyYd/4Czafqz +UBWbAJ+xap6t/WLJCR7goHCVX0DNtpNfzoYK5/rKpQzw0H+L1pB5yghx5GbslthB +xtTb1LjMMl4AUuU5Bv1XLzDZlS/HUYQyefhljlqJPC678KNlegRLjn2YZeZF07X1 +b/KSKDrhAoGBAPVST4JYGS9OoW4Fvu4SV7AJGW1ewHhAmzO1XFrYD8DvSjf3Cinn +ylTYwkQK9ayLLM405Sof2J55NbEakDs5sahN93mqGrk9bWPZrFHgDf0NiMoyI/0N +/ZBXhkBeg9LitBvmEWiBlGK55At0zePWVDcUtXg+d0tSJC4o0y1DoGo7AoGBAMPe +ML95QKabWsCRpGKVwhOFrEp68rZlugwJEjzubC8EXHX8dNy3IURl1j8tSM0kDGay +CDMpxOjqzVyLmLqfIghiG1nkQU7EnJdx86k3AaesHoJff3Ywi+9DwC5r/T3zg20U +Qkr1c4Yxv0Lk3IluHwjPaT/uMd4utlPB6EpAvY6bAoGAdcNBb6yiylbQn2Qat2YO +ue5kSmBFvHQnDLdu0h0N0uwLkLoCIwOl2P0EpG0uadmVdJdnusT203wUDiRWQFf9 +tHFY7wp9MZcPP/NqCROpI2Sv2YAgToW8xuF9DMFSPpWdKBdVG/m4JXxewDEd9NUa +MCa8xjAWTA3uWEo4tW3VP6kCgYAKAYvT/EnFOSKFu+r97lCf1rBajbVghAnhG4WG +/1cff8WJcYA21lQovlsXlySk9jZ7+JRaqMOacoRTOf5vajm+2+Qxz2tWrsyhH/0m +o9y9yBk259IHI6vCaV+j/3hMdeg85lAMrEVekaQHstFhY/LJ7G6gCXcatqAx3zIS +uQP2CQKBgQDGx31nzcrYcJz0EtZPJ5n4JMKrx9S4ZQ2+C7p6oDYXJl2Woh0f+c3K +X1oW1MLFChq+5Or9IVh11cePtV3a6X10Q9xSLQnXdPC9X4QsZoWOUBh5fzw301g1 +WB9ncXqqew3EPHm1G5j4hZ+Gjz/P53TLRYTEYW8fm1Rv9ga5wiJpiz== +-----END RSA PRIVATE KEY----- From cf0b03ca9aca29f5ebfbf986391a354a5df339e4 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Thu, 4 May 2017 19:57:31 -0400 Subject: [PATCH 2/9] Fix the error --- builtin/providers/heroku/resource_heroku_cert.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/providers/heroku/resource_heroku_cert.go b/builtin/providers/heroku/resource_heroku_cert.go index a6390e4e20ea..ab0b2933f10d 100644 --- a/builtin/providers/heroku/resource_heroku_cert.go +++ b/builtin/providers/heroku/resource_heroku_cert.go @@ -89,14 +89,14 @@ func resourceHerokuCertUpdate(d *schema.ResourceData, meta interface{}) error { app := d.Get("app").(string) - if d.HasChange("certificate_chain") { + if d.HasChange("certificate_chain") || d.HasChange("private_key") { preprocess := true rollback := false ad, err := client.SSLEndpointUpdate( context.TODO(), app, d.Id(), heroku.SSLEndpointUpdateOpts{ - CertificateChain: d.Get("certificate_chain").(*string), + CertificateChain: heroku.String(d.Get("certificate_chain").(string)), Preprocess: &preprocess, - PrivateKey: d.Get("private_key").(*string), + PrivateKey: heroku.String(d.Get("private_key").(string)), Rollback: &rollback}) if err != nil { return err From 5e34eb96e723af4c96f01e603d040beffa5d866a Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Thu, 4 May 2017 20:39:47 -0400 Subject: [PATCH 3/9] Fix the test for the update operation --- .../heroku/resource_heroku_cert_test.go | 9 ++- .../heroku/test-fixtures/terraform2.cert | 29 ++++++++ .../heroku/test-fixtures/terraform2.key | 74 ++++++++++++------- 3 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 builtin/providers/heroku/test-fixtures/terraform2.cert diff --git a/builtin/providers/heroku/resource_heroku_cert_test.go b/builtin/providers/heroku/resource_heroku_cert_test.go index 31840887bd01..31cf9fc1bc56 100644 --- a/builtin/providers/heroku/resource_heroku_cert_test.go +++ b/builtin/providers/heroku/resource_heroku_cert_test.go @@ -19,11 +19,14 @@ func TestAccHerokuCert_Basic(t *testing.T) { wd, _ := os.Getwd() certFile := wd + "/test-fixtures/terraform.cert" + certFile2 := wd + "/test-fixtures/terraform2.cert" keyFile := wd + "/test-fixtures/terraform.key" keyFile2 := wd + "/test-fixtures/terraform2.key" certificateChainBytes, _ := ioutil.ReadFile(certFile) certificateChain := string(certificateChainBytes) + certificateChain2Bytes, _ := ioutil.ReadFile(certFile2) + certificateChain2 := string(certificateChain2Bytes) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -41,10 +44,10 @@ func TestAccHerokuCert_Basic(t *testing.T) { ), }, { - Config: testAccCheckHerokuCertConfig(appName, certFile, keyFile2), + Config: testAccCheckHerokuCertConfig(appName, certFile2, keyFile2), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), - testAccCheckHerokuCertificateChain(&endpoint, certificateChain), + testAccCheckHerokuCertificateChain(&endpoint, certificateChain2), resource.TestCheckResourceAttr( "heroku_cert.ssl_certificate", "cname", fmt.Sprintf("%s.herokuapp.com", appName)), @@ -58,7 +61,7 @@ func testAccCheckHerokuCertConfig(appName, certFile, keyFile string) string { return fmt.Sprintf(` resource "heroku_app" "foobar" { name = "%s" - region = "us" + region = "eu" } resource "heroku_addon" "ssl" { diff --git a/builtin/providers/heroku/test-fixtures/terraform2.cert b/builtin/providers/heroku/test-fixtures/terraform2.cert new file mode 100644 index 000000000000..41b7785ee023 --- /dev/null +++ b/builtin/providers/heroku/test-fixtures/terraform2.cert @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0 +QXV0aDAeFw0xNzA1MDUwMDI4NDhaFw0yNzA1MDUwMDI4NTVaMBMxETAPBgNVBAMT +CENlcnRBdXRoMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3f07ApBL +Infz43y96n6iWtQgk4nVEMN2Qc5a4bGm7Ha/gnNGYnv87CGpd6VNBrd07zXlOGXo +5DCly3AxjmFaHw9wzKadXmU2P91tQ4S253tFN8lirMPe+2hS5RnAPw9NsvYsU0Iy +wp/+1a2OpDGtUv00fyU9tY8M1wQo/33xgTyc+8DdEDQ08/PjCKbA5vvpfra5fE+S +g0Gcw8j6Y/iXcnj6LrTvY7I9G3doyAUezGCpAqPErVCDj5nokdJ17zs0kWbr/e4z +o7yKvQOw7majlaX/R6v8tuYvEZ8fokXR7ecGeco86d7sH+OHafOkYQgf+forGMh6 +PSJ5z3WWnLKPvzGgvqoDemGfIyfeRHGTI+e8+4DrcvJGlLS0vBFCYxqXhlvmi6xf +u9G0/zKV/VbIeJS1hTus6sYIIRMzABNwYIGGIz4eBjnO1jakowsdxfgsBvpMwVB+ +yZ+yxv/L9DCVK/VW3VfxQoQ+IDRTokfU/6yKWeonYVtTH57upJ7tRKRy2pmFCJEo +c4T7IKg5ENfGhSkKHuN8CLoWdRREh2KTTijET0qUHCWPbOl9MgW6Y4Jf2qYkggGk +CTRDk7iGuLKT6tMqVrqcmA/AhBpgZKg5N+rIbwTfIHzGNql93bc1FX0KVh7LlV64 +9ZRR4mksrk26pDnLqAfiT15aRsIrYZYdbh0CAwEAAaNFMEMwDgYDVR0PAQH/BAQD +AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFDq5vNYjPHDUyIgkTKCX +9N27PvuiMA0GCSqGSIb3DQEBCwUAA4ICAQCW4RfKiHsFLOwDTTVkQzb0G2A9Ajeg +66lWSuNidntbr+w5595G0ae3qCumaVQSNWKtMAkdahzI+0J00YGWpnqS2rJIIgD+ +8I67EpQ6wi60EUMAECNl7vJvLH/IXt6IVY1wr3ci3G56aKVZIsnaoFi2vxnwHNz3 +uOkNcj0OO4Nosw8aThzsitiddu4BVk+8AFq0cylroQzWjoCrkKOyWMyKTcK6qnS7 +ayyCK02AQPhXFYxet7NVY5hgldto2BAsijBX1Xl6XR5QGSrIQw/2nkAywVSnAGip +Ofk/njzZH9FhUnEY1C5vB2SU310LIOq1evvF8nd7csnI7wdjfHQ3m70PO6p9DGK/ +W0tET8NtuW2JV38KSNMrYxF2Hs7Il92x8JVQu9LtjiKTcJLdnnAQl0OvHUAgAmU9 +BRHOsfWD4Cxiwes0OZHuOpoghh7HV1A+JS5e9qNCCEzarQe4H2Zv8JkeBFbIaEH/ +bcT3a2Rtt6cvDw9mSXSw7p85/810n8af4T1D3aeLFdoVrpeTZVUdyFygcuWo1U4D +JxaRAyJHvi4IJmwpjehn7DoFasNefPBVVFi28QCJXFHpe0DNm8MvI5fGhyZ2uW8t ++6PDgumsZLQT7jJNl9ubYV3U0Nsymvvwqx4LY2nql0agEzJ0F9ekoA50csoxe2ir +/DOgG1nKIc186A== +-----END CERTIFICATE----- diff --git a/builtin/providers/heroku/test-fixtures/terraform2.key b/builtin/providers/heroku/test-fixtures/terraform2.key index 378917eaa25a..c5fee3428f68 100644 --- a/builtin/providers/heroku/test-fixtures/terraform2.key +++ b/builtin/providers/heroku/test-fixtures/terraform2.key @@ -1,27 +1,51 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- From 28178b94ea6460b95bdb6d82231cd9de13ca745e Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Thu, 4 May 2017 22:10:11 -0400 Subject: [PATCH 4/9] Break apart tests for EU vs US to cleanse test run --- .../heroku/resource_heroku_cert_test.go | 72 +++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/builtin/providers/heroku/resource_heroku_cert_test.go b/builtin/providers/heroku/resource_heroku_cert_test.go index 31cf9fc1bc56..7e5aa7bf6e43 100644 --- a/builtin/providers/heroku/resource_heroku_cert_test.go +++ b/builtin/providers/heroku/resource_heroku_cert_test.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/terraform/terraform" ) -func TestAccHerokuCert_Basic(t *testing.T) { +func TestAccHerokuCert_EU(t *testing.T) { var endpoint heroku.SSLEndpointInfoResult appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) @@ -34,7 +34,7 @@ func TestAccHerokuCert_Basic(t *testing.T) { CheckDestroy: testAccCheckHerokuCertDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckHerokuCertConfig(appName, certFile, keyFile), + Config: testAccCheckHerokuCertEUConfig(appName, certFile, keyFile), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), testAccCheckHerokuCertificateChain(&endpoint, certificateChain), @@ -44,7 +44,7 @@ func TestAccHerokuCert_Basic(t *testing.T) { ), }, { - Config: testAccCheckHerokuCertConfig(appName, certFile2, keyFile2), + Config: testAccCheckHerokuCertEUConfig(appName, certFile2, keyFile2), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), testAccCheckHerokuCertificateChain(&endpoint, certificateChain2), @@ -57,7 +57,51 @@ func TestAccHerokuCert_Basic(t *testing.T) { }) } -func testAccCheckHerokuCertConfig(appName, certFile, keyFile string) string { +func TestAccHerokuCert_US(t *testing.T) { + var endpoint heroku.SSLEndpointInfoResult + appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) + + wd, _ := os.Getwd() + certFile := wd + "/test-fixtures/terraform.cert" + certFile2 := wd + "/test-fixtures/terraform2.cert" + keyFile := wd + "/test-fixtures/terraform.key" + keyFile2 := wd + "/test-fixtures/terraform2.key" + + certificateChainBytes, _ := ioutil.ReadFile(certFile) + certificateChain := string(certificateChainBytes) + certificateChain2Bytes, _ := ioutil.ReadFile(certFile2) + certificateChain2 := string(certificateChain2Bytes) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckHerokuCertDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckHerokuCertUSConfig(appName, certFile, keyFile), + Check: resource.ComposeTestCheckFunc( + testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), + testAccCheckHerokuCertificateChain(&endpoint, certificateChain), + resource.TestCheckResourceAttr( + "heroku_cert.ssl_certificate", + "cname", fmt.Sprintf("%s.herokussl.com", appName)), + ), + }, + { + Config: testAccCheckHerokuCertUSConfig(appName, certFile2, keyFile2), + Check: resource.ComposeTestCheckFunc( + testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), + testAccCheckHerokuCertificateChain(&endpoint, certificateChain2), + resource.TestCheckResourceAttr( + "heroku_cert.ssl_certificate", + "cname", fmt.Sprintf("%s.herokussl.com", appName)), + ), + }, + }, + }) +} + +func testAccCheckHerokuCertEUConfig(appName, certFile, keyFile string) string { return fmt.Sprintf(` resource "heroku_app" "foobar" { name = "%s" @@ -77,6 +121,26 @@ resource "heroku_cert" "ssl_certificate" { }`, appName, certFile, keyFile) } +func testAccCheckHerokuCertUSConfig(appName, certFile, keyFile string) string { + return fmt.Sprintf(` +resource "heroku_app" "foobar" { + name = "%s" + region = "us" +} + +resource "heroku_addon" "ssl" { + app = "${heroku_app.foobar.name}" + plan = "ssl:endpoint" +} + +resource "heroku_cert" "ssl_certificate" { + app = "${heroku_app.foobar.name}" + depends_on = ["heroku_addon.ssl"] + certificate_chain="${file("%s")}" + private_key="${file("%s")}" +}`, appName, certFile, keyFile) +} + func testAccCheckHerokuCertDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*heroku.Service) From 5c779d2ad03b12b813537b8e03d970cf81352337 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Thu, 4 May 2017 22:10:36 -0400 Subject: [PATCH 5/9] Refactor Update to more closely match create, increase debug logging --- .../providers/heroku/resource_heroku_cert.go | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/builtin/providers/heroku/resource_heroku_cert.go b/builtin/providers/heroku/resource_heroku_cert.go index ab0b2933f10d..3f5b2a7c7b0d 100644 --- a/builtin/providers/heroku/resource_heroku_cert.go +++ b/builtin/providers/heroku/resource_heroku_cert.go @@ -88,22 +88,24 @@ func resourceHerokuCertUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*heroku.Service) app := d.Get("app").(string) + preprocess := true + rollback := false + opts := heroku.SSLEndpointUpdateOpts{ + CertificateChain: heroku.String(d.Get("certificate_chain").(string)), + Preprocess: &preprocess, + PrivateKey: heroku.String(d.Get("private_key").(string)), + Rollback: &rollback} if d.HasChange("certificate_chain") || d.HasChange("private_key") { - preprocess := true - rollback := false - ad, err := client.SSLEndpointUpdate( - context.TODO(), app, d.Id(), heroku.SSLEndpointUpdateOpts{ - CertificateChain: heroku.String(d.Get("certificate_chain").(string)), - Preprocess: &preprocess, - PrivateKey: heroku.String(d.Get("private_key").(string)), - Rollback: &rollback}) + log.Printf("[DEBUG] SSL Certificate update configuration: %#v, %#v", app, opts) + ad, err := client.SSLEndpointUpdate(context.TODO(), app, d.Id(), opts) if err != nil { - return err + return fmt.Errorf("Error updating SSL endpoint: %s", err) } // Store the new ID d.SetId(ad.ID) + log.Printf("[INFO] Updated SSL Certificate ID: %s", d.Id()) } return resourceHerokuCertRead(d, meta) From 8e91b6cdc865383a04479be7eef35cbd7106f824 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Fri, 5 May 2017 02:42:49 -0400 Subject: [PATCH 6/9] Reflect differences of EU and US regions via separate tests --- .../heroku/resource_heroku_cert_test.go | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/builtin/providers/heroku/resource_heroku_cert_test.go b/builtin/providers/heroku/resource_heroku_cert_test.go index 7e5aa7bf6e43..8767375d0d6e 100644 --- a/builtin/providers/heroku/resource_heroku_cert_test.go +++ b/builtin/providers/heroku/resource_heroku_cert_test.go @@ -5,6 +5,8 @@ import ( "fmt" "io/ioutil" "os" + "regexp" + "strings" "testing" "github.com/cyberdelia/heroku-go/v3" @@ -78,23 +80,23 @@ func TestAccHerokuCert_US(t *testing.T) { CheckDestroy: testAccCheckHerokuCertDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckHerokuCertUSConfig(appName, certFile, keyFile), + Config: testAccCheckHerokuCertUSConfig(appName, certFile2, keyFile2), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), - testAccCheckHerokuCertificateChain(&endpoint, certificateChain), - resource.TestCheckResourceAttr( + testAccCheckHerokuCertificateChain(&endpoint, certificateChain2), + resource.TestMatchResourceAttr( "heroku_cert.ssl_certificate", - "cname", fmt.Sprintf("%s.herokussl.com", appName)), + "cname", regexp.MustCompile(`herokussl`)), ), }, { - Config: testAccCheckHerokuCertUSConfig(appName, certFile2, keyFile2), + Config: testAccCheckHerokuCertUSConfig(appName, certFile, keyFile), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuCertExists("heroku_cert.ssl_certificate", &endpoint), - testAccCheckHerokuCertificateChain(&endpoint, certificateChain2), - resource.TestCheckResourceAttr( + testAccCheckHerokuCertificateChain(&endpoint, certificateChain), + resource.TestMatchResourceAttr( "heroku_cert.ssl_certificate", - "cname", fmt.Sprintf("%s.herokussl.com", appName)), + "cname", regexp.MustCompile(`herokussl`)), ), }, }, @@ -102,7 +104,7 @@ func TestAccHerokuCert_US(t *testing.T) { } func testAccCheckHerokuCertEUConfig(appName, certFile, keyFile string) string { - return fmt.Sprintf(` + return strings.TrimSpace(fmt.Sprintf(` resource "heroku_app" "foobar" { name = "%s" region = "eu" @@ -118,11 +120,11 @@ resource "heroku_cert" "ssl_certificate" { depends_on = ["heroku_addon.ssl"] certificate_chain="${file("%s")}" private_key="${file("%s")}" -}`, appName, certFile, keyFile) +}`, appName, certFile, keyFile)) } func testAccCheckHerokuCertUSConfig(appName, certFile, keyFile string) string { - return fmt.Sprintf(` + return strings.TrimSpace(fmt.Sprintf(` resource "heroku_app" "foobar" { name = "%s" region = "us" @@ -138,7 +140,7 @@ resource "heroku_cert" "ssl_certificate" { depends_on = ["heroku_addon.ssl"] certificate_chain="${file("%s")}" private_key="${file("%s")}" -}`, appName, certFile, keyFile) +}`, appName, certFile, keyFile)) } func testAccCheckHerokuCertDestroy(s *terraform.State) error { From da375cd6a0593456d5d4319d68c7c7ee2a076c08 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Fri, 5 May 2017 10:29:16 -0400 Subject: [PATCH 7/9] Add comment re: why of test breakout --- builtin/providers/heroku/resource_heroku_cert_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/providers/heroku/resource_heroku_cert_test.go b/builtin/providers/heroku/resource_heroku_cert_test.go index 8767375d0d6e..7a90e2a7f286 100644 --- a/builtin/providers/heroku/resource_heroku_cert_test.go +++ b/builtin/providers/heroku/resource_heroku_cert_test.go @@ -15,6 +15,10 @@ import ( "github.com/hashicorp/terraform/terraform" ) +// We break apart testing for EU and US because at present, Heroku deals with +// each a bit differently and the setup/teardown of separate tests seems to +// help them to perform more consistently. +// https://devcenter.heroku.com/articles/ssl-endpoint#add-certificate-and-intermediaries func TestAccHerokuCert_EU(t *testing.T) { var endpoint heroku.SSLEndpointInfoResult appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) From 00d00611919722e2c60e0b1ebea535645beb5f46 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Fri, 5 May 2017 20:08:52 -0400 Subject: [PATCH 8/9] =?UTF-8?q?Removed=20the=20=E2=80=9CSetId=E2=80=9D=20a?= =?UTF-8?q?s=20it=20was=20unnecessary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- builtin/providers/heroku/resource_heroku_cert.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/builtin/providers/heroku/resource_heroku_cert.go b/builtin/providers/heroku/resource_heroku_cert.go index 3f5b2a7c7b0d..8b4d5eacbf69 100644 --- a/builtin/providers/heroku/resource_heroku_cert.go +++ b/builtin/providers/heroku/resource_heroku_cert.go @@ -98,14 +98,10 @@ func resourceHerokuCertUpdate(d *schema.ResourceData, meta interface{}) error { if d.HasChange("certificate_chain") || d.HasChange("private_key") { log.Printf("[DEBUG] SSL Certificate update configuration: %#v, %#v", app, opts) - ad, err := client.SSLEndpointUpdate(context.TODO(), app, d.Id(), opts) + _, err := client.SSLEndpointUpdate(context.TODO(), app, d.Id(), opts) if err != nil { return fmt.Errorf("Error updating SSL endpoint: %s", err) } - - // Store the new ID - d.SetId(ad.ID) - log.Printf("[INFO] Updated SSL Certificate ID: %s", d.Id()) } return resourceHerokuCertRead(d, meta) From 3c05047c33a647be80298cc381da55005f977f6b Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Tue, 9 May 2017 22:29:49 -0400 Subject: [PATCH 9/9] Ensure the SSL Addon has been provisioned --- .../providers/heroku/resource_heroku_addon.go | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/builtin/providers/heroku/resource_heroku_addon.go b/builtin/providers/heroku/resource_heroku_addon.go index ca9123514d09..fe414165b253 100644 --- a/builtin/providers/heroku/resource_heroku_addon.go +++ b/builtin/providers/heroku/resource_heroku_addon.go @@ -6,8 +6,10 @@ import ( "log" "strings" "sync" + "time" "github.com/cyberdelia/heroku-go/v3" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) @@ -89,6 +91,20 @@ func resourceHerokuAddonCreate(d *schema.ResourceData, meta interface{}) error { d.SetId(a.ID) log.Printf("[INFO] Addon ID: %s", d.Id()) + // Wait for the Addon to be provisioned + log.Printf("[DEBUG] Waiting for Addon (%s) to be provisioned", d.Id()) + stateConf := &resource.StateChangeConf{ + Pending: []string{"provisioning"}, + Target: []string{"provisioned"}, + Refresh: AddOnStateRefreshFunc(client, app, d.Id()), + Timeout: 20 * time.Minute, + } + + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("Error waiting for Addon (%s) to be provisioned: %s", d.Id(), err) + } + log.Printf("[INFO] Addon provisioned: %s", d.Id()) + return resourceHerokuAddonRead(d, meta) } @@ -167,3 +183,18 @@ func resourceHerokuAddonRetrieve(app string, id string, client *heroku.Service) return addon, nil } + +// AddOnStateRefreshFunc returns a resource.StateRefreshFunc that is used to +// watch an AddOn. +func AddOnStateRefreshFunc(client *heroku.Service, appID, addOnID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + addon, err := client.AddOnInfo(context.TODO(), appID, addOnID) + if err != nil { + return nil, "", err + } + + // The type conversion here can be dropped when the vendored version of + // heroku-go is updated. + return (*heroku.AddOn)(addon), addon.State, nil + } +}