Merge remote-tracking branch 'origin/master' into f-oracle-compute

This commit is contained in:
Jake Champlin 2017-04-09 21:58:01 -04:00
commit dec1cc28f0
No known key found for this signature in database
GPG Key ID: DC31F41958EF4AC2
44 changed files with 661 additions and 121 deletions

View File

@ -2,6 +2,7 @@
FEATURES:
* **New Resource:** `aws_iam_openid_connect_provider` [GH-13456]
* **New Resource:** `aws_lightsail_static_ip` [GH-13175]
* **New Resource:** `aws_lightsail_static_ip_attachment` [GH-13207]
* **New Resource:** `aws_ses_domain_identity` [GH-13098]
@ -75,9 +76,11 @@ BUG FIXES:
* provider/aws: Fix DynamoDB issues about GSIs indexes [GH-13256]
* provider/aws: Fix `aws_s3_bucket` drift detection of logging options [GH-13281]
* provider/aws: Update ElasticTranscoderPreset to have default for MaxFrameRate [GH-13422]
* provider/aws: Fix aws_ami_launch_permission refresh when AMI disappears [GH-13469]
* provider/azurerm: Network Security Group - ignoring protocol casing at Import time [GH-13153]
* provider/azurerm: Fix crash when importing Local Network Gateways [GH-13261]
* provider/bitbucket: Fixed issue where provider would fail with an "EOF" error on some operations [GH-13390]
* provider/ns1: No splitting answer on SPF records. [GH-13260]
* provider/openstack: Refresh volume_attachment from state if NotFound [GH-13342]
* provider/openstack: Add SOFT_DELETED to delete status [GH-13444]
* provider/profitbricks: Changed output type of ips variable of ip_block ProfitBricks resource [GH-13290]

View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"log"
"net/url"
"strings"
"github.com/hashicorp/terraform/helper/schema"
@ -58,3 +59,19 @@ func suppressEquivalentJsonDiffs(k, old, new string, d *schema.ResourceData) boo
return jsonBytesEqual(ob.Bytes(), nb.Bytes())
}
func suppressOpenIdURL(k, old, new string, d *schema.ResourceData) bool {
oldUrl, err := url.Parse(old)
if err != nil {
return false
}
newUrl, err := url.Parse(new)
if err != nil {
return false
}
oldUrl.Scheme = "https"
return oldUrl.String() == newUrl.String()
}

View File

@ -309,6 +309,7 @@ func Provider() terraform.ResourceProvider {
"aws_iam_group_membership": resourceAwsIamGroupMembership(),
"aws_iam_group_policy_attachment": resourceAwsIamGroupPolicyAttachment(),
"aws_iam_instance_profile": resourceAwsIamInstanceProfile(),
"aws_iam_openid_connect_provider": resourceAwsIamOpenIDConnectProvider(),
"aws_iam_policy": resourceAwsIamPolicy(),
"aws_iam_policy_attachment": resourceAwsIamPolicyAttachment(),
"aws_iam_role_policy_attachment": resourceAwsIamRolePolicyAttachment(),

View File

@ -2,7 +2,11 @@ package aws
import (
"fmt"
"log"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)
@ -92,6 +96,12 @@ func hasLaunchPermission(conn *ec2.EC2, image_id string, account_id string) (boo
Attribute: aws.String("launchPermission"),
})
if err != nil {
// When an AMI disappears out from under a launch permission resource, we will
// see either InvalidAMIID.NotFound or InvalidAMIID.Unavailable.
if ec2err, ok := err.(awserr.Error); ok && strings.HasPrefix(ec2err.Code(), "InvalidAMIID") {
log.Printf("[DEBUG] %s no longer exists, so we'll drop launch permission for %s from the state", image_id, account_id)
return false, nil
}
return false, err
}

View File

@ -2,15 +2,18 @@ package aws
import (
"fmt"
r "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"os"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
r "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAMILaunchPermission_Basic(t *testing.T) {
image_id := ""
account_id := os.Getenv("AWS_ACCOUNT_ID")
imageID := ""
accountID := os.Getenv("AWS_ACCOUNT_ID")
r.Test(t, r.TestCase{
PreCheck: func() {
@ -23,19 +26,36 @@ func TestAccAWSAMILaunchPermission_Basic(t *testing.T) {
Steps: []r.TestStep{
// Scaffold everything
r.TestStep{
Config: testAccAWSAMILaunchPermissionConfig(account_id, true),
Config: testAccAWSAMILaunchPermissionConfig(accountID, true),
Check: r.ComposeTestCheckFunc(
testCheckResourceGetAttr("aws_ami_copy.test", "id", &image_id),
testAccAWSAMILaunchPermissionExists(account_id, &image_id),
testCheckResourceGetAttr("aws_ami_copy.test", "id", &imageID),
testAccAWSAMILaunchPermissionExists(accountID, &imageID),
),
},
// Drop just launch permission to test destruction
r.TestStep{
Config: testAccAWSAMILaunchPermissionConfig(account_id, false),
Config: testAccAWSAMILaunchPermissionConfig(accountID, false),
Check: r.ComposeTestCheckFunc(
testAccAWSAMILaunchPermissionDestroyed(account_id, &image_id),
testAccAWSAMILaunchPermissionDestroyed(accountID, &imageID),
),
},
// Re-add everything so we can test when AMI disappears
r.TestStep{
Config: testAccAWSAMILaunchPermissionConfig(accountID, true),
Check: r.ComposeTestCheckFunc(
testCheckResourceGetAttr("aws_ami_copy.test", "id", &imageID),
testAccAWSAMILaunchPermissionExists(accountID, &imageID),
),
},
// Here we delete the AMI to verify the follow-on refresh after this step
// should not error.
r.TestStep{
Config: testAccAWSAMILaunchPermissionConfig(accountID, true),
Check: r.ComposeTestCheckFunc(
testAccAWSAMIDisappears(&imageID),
),
ExpectNonEmptyPlan: true,
},
},
})
}
@ -58,31 +78,53 @@ func testCheckResourceGetAttr(name, key string, value *string) r.TestCheckFunc {
}
}
func testAccAWSAMILaunchPermissionExists(account_id string, image_id *string) r.TestCheckFunc {
func testAccAWSAMILaunchPermissionExists(accountID string, imageID *string) r.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
if has, err := hasLaunchPermission(conn, *image_id, account_id); err != nil {
if has, err := hasLaunchPermission(conn, *imageID, accountID); err != nil {
return err
} else if !has {
return fmt.Errorf("launch permission does not exist for '%s' on '%s'", account_id, *image_id)
return fmt.Errorf("launch permission does not exist for '%s' on '%s'", accountID, *imageID)
}
return nil
}
}
func testAccAWSAMILaunchPermissionDestroyed(account_id string, image_id *string) r.TestCheckFunc {
func testAccAWSAMILaunchPermissionDestroyed(accountID string, imageID *string) r.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
if has, err := hasLaunchPermission(conn, *image_id, account_id); err != nil {
if has, err := hasLaunchPermission(conn, *imageID, accountID); err != nil {
return err
} else if has {
return fmt.Errorf("launch permission still exists for '%s' on '%s'", account_id, *image_id)
return fmt.Errorf("launch permission still exists for '%s' on '%s'", accountID, *imageID)
}
return nil
}
}
func testAccAWSAMILaunchPermissionConfig(account_id string, includeLaunchPermission bool) string {
// testAccAWSAMIDisappears is technically a "test check function" but really it
// exists to perform a side effect of deleting an AMI out from under a resource
// so we can test that Terraform will react properly
func testAccAWSAMIDisappears(imageID *string) r.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
req := &ec2.DeregisterImageInput{
ImageId: aws.String(*imageID),
}
_, err := conn.DeregisterImage(req)
if err != nil {
return err
}
if err := resourceAwsAmiWaitForDestroy(*imageID, conn); err != nil {
return err
}
return nil
}
}
func testAccAWSAMILaunchPermissionConfig(accountID string, includeLaunchPermission bool) string {
base := `
resource "aws_ami_copy" "test" {
name = "launch-permission-test"
@ -101,5 +143,5 @@ resource "aws_ami_launch_permission" "self-test" {
image_id = "${aws_ami_copy.test.id}"
account_id = "%s"
}
`, account_id)
`, accountID)
}

View File

@ -317,6 +317,7 @@ resource "aws_db_instance" "bar" {
maintenance_window = "Fri:09:00-Fri:09:30"
backup_retention_period = 0
skip_final_snapshot = true
option_group_name = "${aws_db_option_group.bar.name}"
}

View File

@ -317,7 +317,6 @@ resource "aws_efs_file_system" "foo" {
func testAccAWSEFSFileSystemConfigPagedTags(rInt int) string {
return fmt.Sprintf(`
resource "aws_efs_file_system" "foo" {
creation_token = "radeksimko"
tags {
Name = "foo-efs-%d"
Another = "tag"
@ -338,7 +337,6 @@ func testAccAWSEFSFileSystemConfigPagedTags(rInt int) string {
func testAccAWSEFSFileSystemConfigWithTags(rInt int) string {
return fmt.Sprintf(`
resource "aws_efs_file_system" "foo-with-tags" {
creation_token = "yada_yada"
tags {
Name = "foo-efs-%d"
Another = "tag"

View File

@ -0,0 +1,141 @@
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsIamOpenIDConnectProvider() *schema.Resource {
return &schema.Resource{
Create: resourceAwsIamOpenIDConnectProviderCreate,
Read: resourceAwsIamOpenIDConnectProviderRead,
Update: resourceAwsIamOpenIDConnectProviderUpdate,
Delete: resourceAwsIamOpenIDConnectProviderDelete,
Exists: resourceAwsIamOpenIDConnectProviderExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"url": &schema.Schema{
Type: schema.TypeString,
Computed: false,
Required: true,
ForceNew: true,
ValidateFunc: validateOpenIdURL,
DiffSuppressFunc: suppressOpenIdURL,
},
"client_id_list": &schema.Schema{
Elem: &schema.Schema{Type: schema.TypeString},
Type: schema.TypeList,
Required: true,
ForceNew: true,
},
"thumbprint_list": &schema.Schema{
Elem: &schema.Schema{Type: schema.TypeString},
Type: schema.TypeList,
Required: true,
},
},
}
}
func resourceAwsIamOpenIDConnectProviderCreate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
input := &iam.CreateOpenIDConnectProviderInput{
Url: aws.String(d.Get("url").(string)),
ClientIDList: expandStringList(d.Get("client_id_list").([]interface{})),
ThumbprintList: expandStringList(d.Get("thumbprint_list").([]interface{})),
}
out, err := iamconn.CreateOpenIDConnectProvider(input)
if err != nil {
return err
}
d.SetId(*out.OpenIDConnectProviderArn)
return resourceAwsIamOpenIDConnectProviderRead(d, meta)
}
func resourceAwsIamOpenIDConnectProviderRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
input := &iam.GetOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(d.Id()),
}
out, err := iamconn.GetOpenIDConnectProvider(input)
if err != nil {
return err
}
d.Set("arn", d.Id())
d.Set("url", out.Url)
d.Set("client_id_list", flattenStringList(out.ClientIDList))
d.Set("thumbprint_list", flattenStringList(out.ThumbprintList))
return nil
}
func resourceAwsIamOpenIDConnectProviderUpdate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
if d.HasChange("thumbprint_list") {
input := &iam.UpdateOpenIDConnectProviderThumbprintInput{
OpenIDConnectProviderArn: aws.String(d.Id()),
ThumbprintList: expandStringList(d.Get("thumbprint_list").([]interface{})),
}
_, err := iamconn.UpdateOpenIDConnectProviderThumbprint(input)
if err != nil {
return err
}
}
return resourceAwsIamOpenIDConnectProviderRead(d, meta)
}
func resourceAwsIamOpenIDConnectProviderDelete(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
input := &iam.DeleteOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(d.Id()),
}
_, err := iamconn.DeleteOpenIDConnectProvider(input)
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() == "NoSuchEntity" {
return nil
}
return fmt.Errorf("Error deleting platform application %s", err)
}
return nil
}
func resourceAwsIamOpenIDConnectProviderExists(d *schema.ResourceData, meta interface{}) (bool, error) {
iamconn := meta.(*AWSClient).iamconn
input := &iam.GetOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(d.Id()),
}
_, err := iamconn.GetOpenIDConnectProvider(input)
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() == "NoSuchEntity" {
return false, nil
}
return true, err
}
return true, nil
}

View File

@ -0,0 +1,187 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMOpenIDConnectProvider_basic(t *testing.T) {
rString := acctest.RandString(5)
url := "accounts.google.com/" + rString
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccIAMOpenIDConnectProviderConfig(rString),
Check: resource.ComposeTestCheckFunc(
testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "url", url),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.#", "1"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.0",
"266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.#", "0"),
),
},
resource.TestStep{
Config: testAccIAMOpenIDConnectProviderConfig_modified(rString),
Check: resource.ComposeTestCheckFunc(
testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "url", url),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.#", "1"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.0",
"266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.#", "2"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.0", "cf23df2207d99a74fbe169e3eba035e633b65d94"),
resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.1", "c784713d6f9cb67b55dd84f4e4af7832d42b8f55"),
),
},
},
})
}
func TestAccAWSIAMOpenIDConnectProvider_importBasic(t *testing.T) {
resourceName := "aws_iam_openid_connect_provider.goog"
rString := acctest.RandString(5)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccIAMOpenIDConnectProviderConfig_modified(rString),
},
resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccAWSIAMOpenIDConnectProvider_disappears(t *testing.T) {
rString := acctest.RandString(5)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccIAMOpenIDConnectProviderConfig(rString),
Check: resource.ComposeTestCheckFunc(
testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"),
testAccCheckIAMOpenIDConnectProviderDisappears("aws_iam_openid_connect_provider.goog"),
),
ExpectNonEmptyPlan: true,
},
},
})
}
func testAccCheckIAMOpenIDConnectProviderDestroy(s *terraform.State) error {
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_iam_openid_connect_provider" {
continue
}
input := &iam.GetOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(rs.Primary.ID),
}
out, err := iamconn.GetOpenIDConnectProvider(input)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
// none found, that's good
return nil
}
return fmt.Errorf("Error reading IAM OpenID Connect Provider, out: %s, err: %s", out, err)
}
if out != nil {
return fmt.Errorf("Found IAM OpenID Connect Provider, expected none: %s", out)
}
}
return nil
}
func testAccCheckIAMOpenIDConnectProviderDisappears(id string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[id]
if !ok {
return fmt.Errorf("Not Found: %s", id)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
_, err := iamconn.DeleteOpenIDConnectProvider(&iam.DeleteOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(rs.Primary.ID),
})
return err
}
}
func testAccCheckIAMOpenIDConnectProvider(id string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[id]
if !ok {
return fmt.Errorf("Not Found: %s", id)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
_, err := iamconn.GetOpenIDConnectProvider(&iam.GetOpenIDConnectProviderInput{
OpenIDConnectProviderArn: aws.String(rs.Primary.ID),
})
if err != nil {
return err
}
return nil
}
}
func testAccIAMOpenIDConnectProviderConfig(rString string) string {
return fmt.Sprintf(`
resource "aws_iam_openid_connect_provider" "goog" {
url="https://accounts.google.com/%s"
client_id_list = [
"266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"
]
thumbprint_list = []
}
`, rString)
}
func testAccIAMOpenIDConnectProviderConfig_modified(rString string) string {
return fmt.Sprintf(`
resource "aws_iam_openid_connect_provider" "goog" {
url="https://accounts.google.com/%s"
client_id_list = [
"266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"
]
thumbprint_list = ["cf23df2207d99a74fbe169e3eba035e633b65d94", "c784713d6f9cb67b55dd84f4e4af7832d42b8f55"]
}
`, rString)
}

View File

@ -3,6 +3,7 @@ package aws
import (
"fmt"
"net"
"net/url"
"regexp"
"strings"
"time"
@ -1170,3 +1171,19 @@ func validateAwsAlbTargetGroupNamePrefix(v interface{}, k string) (ws []string,
}
return
}
func validateOpenIdURL(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
u, err := url.Parse(value)
if err != nil {
errors = append(errors, fmt.Errorf("%q has to be a valid URL", k))
return
}
if u.Scheme != "https" {
errors = append(errors, fmt.Errorf("%q has to use HTTPS scheme (i.e. begin with https://)", k))
}
if len(u.Query()) > 0 {
errors = append(errors, fmt.Errorf("%q cannot contain query parameters per the OIDC standard", k))
}
return
}

View File

@ -1913,3 +1913,35 @@ func TestValidateDbOptionGroupNamePrefix(t *testing.T) {
}
}
}
func TestValidateOpenIdURL(t *testing.T) {
cases := []struct {
Value string
ErrCount int
}{
{
Value: "http://wrong.scheme.com",
ErrCount: 1,
},
{
Value: "ftp://wrong.scheme.co.uk",
ErrCount: 1,
},
{
Value: "%@invalidUrl",
ErrCount: 1,
},
{
Value: "https://example.com/?query=param",
ErrCount: 1,
},
}
for _, tc := range cases {
_, errors := validateOpenIdURL(tc.Value, "url")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected %d of OpenID URL validation errors, got %d", tc.ErrCount, len(errors))
}
}
}

View File

@ -17,7 +17,7 @@ func TestAccDnsCnameRecordSet_Basic(t *testing.T) {
host = "www.hashicorp.com"
}
`,
"s.shared.global.fastly.net.",
"dualstack.s.shared.global.fastly.net.",
},
}

View File

@ -236,7 +236,7 @@ func resourceDataToRecord(r *dns.Record, d *schema.ResourceData) error {
var a *dns.Answer
v := answer["answer"].(string)
switch d.Get("type") {
case "TXT":
case "TXT", "SPF":
a = dns.NewTXTAnswer(v)
default:
a = dns.NewAnswer(strings.Split(v, " "))

View File

@ -71,6 +71,27 @@ func TestAccRecord_updated(t *testing.T) {
})
}
func TestAccRecord_SPF(t *testing.T) {
var record dns.Record
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRecordDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRecordSPF,
Check: resource.ComposeTestCheckFunc(
testAccCheckRecordExists("ns1_record.spf", &record),
testAccCheckRecordDomain(&record, "terraform-record-test.io"),
testAccCheckRecordTTL(&record, 86400),
testAccCheckRecordUseClientSubnet(&record, true),
testAccCheckRecordAnswerRdata(&record, "v=DKIM1; k=rsa; p=XXXXXXXX"),
),
},
},
})
}
func testAccCheckRecordExists(n string, record *dns.Record) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -297,3 +318,20 @@ resource "ns1_zone" "test" {
zone = "terraform-record-test.io"
}
`
const testAccRecordSPF = `
resource "ns1_record" "spf" {
zone = "${ns1_zone.test.zone}"
domain = "${ns1_zone.test.zone}"
type = "SPF"
ttl = 86400
use_client_subnet = "true"
answers = {
answer = "v=DKIM1; k=rsa; p=XXXXXXXX"
}
}
resource "ns1_zone" "test" {
zone = "terraform-record-test.io"
}
`

View File

@ -123,22 +123,27 @@ func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) {
// Get our configuration
rc := *n.Config
for k, v := range rc.Config {
var vString string
if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
n.VariableValues[k] = vString
continue
}
vKind := reflect.ValueOf(v).Type().Kind()
var vMap map[string]interface{}
if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
n.VariableValues[k] = vMap
continue
}
var vSlice []interface{}
if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
n.VariableValues[k] = vSlice
continue
switch vKind {
case reflect.Slice:
var vSlice []interface{}
if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
n.VariableValues[k] = vSlice
continue
}
case reflect.Map:
var vMap map[string]interface{}
if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
n.VariableValues[k] = vMap
continue
}
default:
var vString string
if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
n.VariableValues[k] = vString
continue
}
}
return nil, fmt.Errorf("Variable value for %s is not a string, list or map type", k)

View File

@ -0,0 +1,45 @@
---
layout: "aws"
page_title: "AWS: aws_iam_openid_connect_provider"
sidebar_current: "docs-aws-resource-iam-openid-connect-provider"
description: |-
Provides an IAM OpenID Connect provider.
---
# aws\_iam\_openid\_connect\_provider
Provides an IAM OpenID Connect provider.
## Example Usage
```
resource "aws_iam_openid_connect_provider" "default" {
url = "https://accounts.google.com"
client_id_list = [
"266362248691-342342xasdasdasda-apps.googleusercontent.com"
]
thumbprint_list = []
}
```
## Argument Reference
The following arguments are supported:
* `url` - (Required) The URL of the identity provider. Corresponds to the _iss_ claim.
* `client_id_list` - (Required) A list of client IDs (also known as audiences). When a mobile or web app registers with an OpenID Connect provider, they establish a value that identifies the application. (This is the value that's sent as the client_id parameter on OAuth requests.)
* `thumbprint_list` - (Required) A list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s).
## Attributes Reference
The following attributes are exported:
* `arn` - The ARN assigned by AWS for this provider.
## Import
IAM OpenID Connect Providers can be imported using the `arn`, e.g.
```
$ terraform import aws_iam_openid_connect_provider.default arn:aws:iam::123456789012:oidc-provider/accounts.google.com
```

View File

@ -27,7 +27,7 @@ configurations that are applied within Terraform Enterprise.
## Example Usage
```
```hcl
data "external" "example" {
program = ["python", "${path.module}/example-data-source.py"]
@ -94,7 +94,7 @@ language.
The following example shows some input/output boilerplate code for a
data source implemented in bash:
```
```bash
#!/bin/bash
# Exit if any of the intermediate steps fail

View File

@ -18,7 +18,7 @@ Use the navigation to the left to read about the available resources.
The following is a minimal example:
```
```hcl
# Configure the MySQL provider
provider "mysql" {
endpoint = "my-database.example.com:3306"
@ -36,7 +36,7 @@ This provider can be used in conjunction with other resources that create
MySQL servers. For example, ``aws_db_instance`` is able to create MySQL
servers in Amazon's RDS service.
```
```hcl
# Create a database server
resource "aws_db_instance" "default" {
engine = "mysql"

View File

@ -19,7 +19,7 @@ on your database resources as an extra safety measure.
## Example Usage
```
```hcl
resource "mysql_database" "app" {
name = "my_awesome_app"
}

View File

@ -13,7 +13,7 @@ a user on a MySQL server.
## Example Usage
```
```hcl
resource "mysql_user" "jdoe" {
user = "jdoe"
host = "example.com"

View File

@ -16,7 +16,7 @@ server.
## Example Usage
```
```hcl
resource "mysql_user" "jdoe" {
user = "jdoe"
host = "example.com"

View File

@ -43,7 +43,7 @@ the same until new random values are desired.
For example:
```
```hcl
resource "random_id" "server" {
keepers = {
# Generate a new id each time we switch to a new AMI id

View File

@ -26,7 +26,7 @@ exist concurrently.
The following example shows how to generate a unique name for an AWS EC2
instance that changes each time a new AMI id is selected.
```
```hcl
resource "random_id" "server" {
keepers = {
# Generate a new id each time we switch to a new AMI id

View File

@ -21,7 +21,7 @@ exist concurrently.
The following example shows how to generate a unique pet name for an AWS EC2
instance that changes each time a new AMI id is selected.
```
```hcl
resource "random_pet" "server" {
keepers = {
# Generate a new pet name each time we switch to a new AMI id

View File

@ -13,7 +13,7 @@ of strings given as an argument.
## Example Usage
```
```hcl
resource "random_shuffle" "az" {
input = ["us-west-1a", "us-west-1c", "us-west-1d", "us-west-1e"]
result_count = 2

View File

@ -30,7 +30,7 @@ Use the navigation to the left to read about the available resources.
## Example Usage
```
```hcl
provider "rundeck" {
url = "http://rundeck.example.com/"
auth_token = "abcd1234"

View File

@ -16,7 +16,7 @@ Each job belongs to a project. A project can be created with the `rundeck_projec
## Example Usage
```
```hcl
resource "rundeck_job" "bounceweb" {
name = "Bounce Web Servers"
project_name = "anvils"

View File

@ -14,7 +14,7 @@ it runs commands.
## Example Usage
```
```hcl
resource "rundeck_private_key" "anvils" {
path = "anvils/id_rsa"
key_material = "${file("/id_rsa")}"

View File

@ -14,7 +14,7 @@ can be run on.
## Example Usage
```
```hcl
resource "rundeck_project" "anvils" {
name = "anvils"
description = "Application for managing Anvils"

View File

@ -17,7 +17,7 @@ may be used in the configuration of other resources such as ``aws_key_pair``.
## Example Usage
```
```hcl
resource "rundeck_public_key" "anvils" {
path = "anvils/id_rsa.pub"
key_material = "ssh-rsa yada-yada-yada"

View File

@ -12,7 +12,7 @@ Renders a multi-part cloud-init config from source files.
## Example Usage
```
```hcl
# Render a part using a `template_file`
data "template_file" "script" {
template = "${file("${path.module}/init.tpl")}"

View File

@ -16,7 +16,7 @@ Option 1: From a file:
Reference the template path:
```
```hcl
data "template_file" "init" {
template = "${file("${path.module}/init.tpl")}"
@ -28,7 +28,7 @@ data "template_file" "init" {
Inside the file, reference the variable as such:
```
```bash
#!/bin/bash
echo "CONSUL_ADDRESS = ${consul_address}" > /tmp/iplist
@ -36,7 +36,7 @@ echo "CONSUL_ADDRESS = ${consul_address}" > /tmp/iplist
Option 2: Inline:
```
```hcl
data "template_file" "init" {
template = "$${consul_address}:1234"

View File

@ -15,7 +15,7 @@ Use the navigation to the left to read about the available data sources.
## Example Usage
```
```hcl
# Template for initial configuration bash script
data "template_file" "init" {
template = "${file("init.tpl")}"
@ -35,7 +35,7 @@ resource "aws_instance" "web" {
Or using an inline template:
```
```hcl
# Template for initial configuration bash script
data "template_file" "init" {
template = "$${consul_address}:1234"

View File

@ -15,7 +15,7 @@ Use the navigation to the left to read about the available data sources.
## Example Usage
```
```hcl
# Shared infrastructure state stored in Atlas
data "terraform_remote_state" "vpc" {
backend = "atlas"

View File

@ -26,7 +26,7 @@ Use the navigation to the left to read about the available resources.
## Example Usage
```
```hcl
## This example create a self-signed certificate for a development
## environment.
## THIS IS NOT RECOMMENDED FOR PRODUCTION SERVICES.
@ -34,39 +34,39 @@ Use the navigation to the left to read about the available resources.
## security considerations and other practical tradeoffs.
resource "tls_private_key" "example" {
algorithm = "ECDSA"
algorithm = "ECDSA"
}
resource "tls_self_signed_cert" "example" {
key_algorithm = "${tls_private_key.example.algorithm}"
private_key_pem = "${tls_private_key.example.private_key_pem}"
key_algorithm = "${tls_private_key.example.algorithm}"
private_key_pem = "${tls_private_key.example.private_key_pem}"
# Certificate expires after 12 hours.
validity_period_hours = 12
# Certificate expires after 12 hours.
validity_period_hours = 12
# Generate a new certificate if Terraform is run within three
# hours of the certificate's expiration time.
early_renewal_hours = 3
# Generate a new certificate if Terraform is run within three
# hours of the certificate's expiration time.
early_renewal_hours = 3
# Reasonable set of uses for a server SSL certificate.
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
# Reasonable set of uses for a server SSL certificate.
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
dns_names = ["example.com", "example.net"]
dns_names = ["example.com", "example.net"]
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
}
# For example, this can be used to populate an AWS IAM server certificate.
resource "aws_iam_server_certificate" "example" {
name = "example_self_signed_cert"
certificate_body = "${tls_self_signed_cert.example.cert_pem}"
private_key = "${tls_private_key.example.private_key_pem}"
name = "example_self_signed_cert"
certificate_body = "${tls_self_signed_cert.example.cert_pem}"
private_key = "${tls_private_key.example.private_key_pem}"
}
```

View File

@ -26,15 +26,15 @@ resource form.
## Example Usage
```
```hcl
resource "tls_cert_request" "example" {
key_algorithm = "ECDSA"
private_key_pem = "${file(\"private_key.pem\")}"
key_algorithm = "ECDSA"
private_key_pem = "${file("private_key.pem")}"
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
}
```

View File

@ -17,21 +17,20 @@ or when deployed internally to an organization.
## Example Usage
```
```hcl
resource "tls_locally_signed_cert" "example" {
cert_request_pem = "${file(\"cert_request.pem\")}"
cert_request_pem = "${file("cert_request.pem")}"
ca_key_algorithm = "ECDSA"
ca_private_key_pem = "${file("ca_private_key.pem")}"
ca_cert_pem = "${file("ca_cert.pem")}"
ca_key_algorithm = "ECDSA"
ca_private_key_pem = "${file(\"ca_private_key.pem\")}"
ca_cert_pem = "${file(\"ca_cert.pem\")}"
validity_period_hours = 12
validity_period_hours = 12
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}
```

View File

@ -23,10 +23,10 @@ state and does not create any external managed resources.
## Example Usage
```
```hcl
resource "tls_private_key" "example" {
algorithm = "ECDSA"
ecdsa_curve = "P384"
algorithm = "ECDSA"
ecdsa_curve = "P384"
}
```

View File

@ -27,23 +27,23 @@ Load Balancer*, *Elastic Beanstalk*, *CloudFront* or *OpsWorks*.
## Example Usage
```
```hcl
resource "tls_self_signed_cert" "example" {
key_algorithm = "ECDSA"
private_key_pem = "${file(\"private_key.pem\")}"
key_algorithm = "ECDSA"
private_key_pem = "${file(\"private_key.pem\")}"
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
validity_period_hours = 12
validity_period_hours = 12
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}
```

View File

@ -25,7 +25,7 @@ for more details.
## Example Usage
```
```hcl
data "vault_generic_secret" "rundeck_auth" {
path = "secret/rundeck_auth"
}

View File

@ -126,7 +126,7 @@ The `client_auth` configuration block accepts the following arguments:
## Example Usage
```
```hcl
provider "vault" {
# It is strongly recommended to configure this provider through the
# environment variables described above, so that each user can have

View File

@ -25,7 +25,7 @@ for more details.
## Example Usage
```
```hcl
resource "vault_generic_secret" "example" {
path = "secret/foo"

View File

@ -11,7 +11,7 @@ description: |-
## Example Usage
```
```hcl
resource "vault_policy" "example" {
name = "dev-team"

View File

@ -745,6 +745,10 @@
<a href="/docs/providers/aws/r/iam_instance_profile.html">aws_iam_instance_profile</a>
</li>
<li<%= sidebar_current("docs-aws-resource-iam-openid-connect-provider") %>>
<a href="/docs/providers/aws/r/iam_openid_connect_provider.html">aws_iam_openid_connect_provider</a>
</li>
<li<%= sidebar_current("docs-aws-resource-iam-policy") %>>
<a href="/docs/providers/aws/r/iam_policy.html">aws_iam_policy</a>
</li>