Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add name_prefix support to aws_cloudwatch_log_group #13273

Merged
merged 1 commit into from
Apr 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions builtin/providers/aws/resource_aws_cloudwatch_log_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

"github.com/aws/aws-sdk-go/aws"
Expand All @@ -24,10 +25,18 @@ func resourceAwsCloudWatchLogGroup() *schema.Resource {

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name_prefix"},
ValidateFunc: validateLogGroupName,
},
"name_prefix": {
Type: schema.TypeString,
Required: true,
Optional: true,
ForceNew: true,
ValidateFunc: validateLogGroupName,
ValidateFunc: validateLogGroupNamePrefix,
},

"retention_in_days": {
Expand All @@ -49,10 +58,19 @@ func resourceAwsCloudWatchLogGroup() *schema.Resource {
func resourceAwsCloudWatchLogGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatchlogsconn

log.Printf("[DEBUG] Creating CloudWatch Log Group: %s", d.Get("name").(string))
var logGroupName string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to think we should refactor this type of code into a common structure fund - it is repeated in a lot of places now - thoughts?

We could pass name, name_prefix and return the formatted value

Thoughts?

if v, ok := d.GetOk("name"); ok {
logGroupName = v.(string)
} else if v, ok := d.GetOk("name_prefix"); ok {
logGroupName = resource.PrefixedUniqueId(v.(string))
} else {
logGroupName = resource.UniqueId()
}

log.Printf("[DEBUG] Creating CloudWatch Log Group: %s", logGroupName)

_, err := conn.CreateLogGroup(&cloudwatchlogs.CreateLogGroupInput{
LogGroupName: aws.String(d.Get("name").(string)),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceAlreadyExistsException" {
Expand All @@ -61,7 +79,7 @@ func resourceAwsCloudWatchLogGroupCreate(d *schema.ResourceData, meta interface{
return fmt.Errorf("Creating CloudWatch Log Group failed: %s '%s'", err, d.Get("name"))
}

d.SetId(d.Get("name").(string))
d.SetId(logGroupName)

log.Println("[INFO] CloudWatch Log Group created")

Expand Down
48 changes: 48 additions & 0 deletions builtin/providers/aws/resource_aws_cloudwatch_log_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
Expand Down Expand Up @@ -30,6 +31,43 @@ func TestAccAWSCloudWatchLogGroup_basic(t *testing.T) {
})
}

func TestAccAWSCloudWatchLogGroup_namePrefix(t *testing.T) {
var lg cloudwatchlogs.LogGroup

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchLogGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudWatchLogGroup_namePrefix,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchLogGroupExists("aws_cloudwatch_log_group.test", &lg),
resource.TestMatchResourceAttr("aws_cloudwatch_log_group.test", "name", regexp.MustCompile("^tf-test-")),
),
},
},
})
}

func TestAccAWSCloudWatchLogGroup_generatedName(t *testing.T) {
var lg cloudwatchlogs.LogGroup

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchLogGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudWatchLogGroup_generatedName,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchLogGroupExists("aws_cloudwatch_log_group.test", &lg),
),
},
},
})
}

func TestAccAWSCloudWatchLogGroup_retentionPolicy(t *testing.T) {
var lg cloudwatchlogs.LogGroup
rInt := acctest.RandInt()
Expand Down Expand Up @@ -256,3 +294,13 @@ resource "aws_cloudwatch_log_group" "charlie" {
}
`, rInt, rInt+1, rInt+2)
}

const testAccAWSCloudWatchLogGroup_namePrefix = `
resource "aws_cloudwatch_log_group" "test" {
name_prefix = "tf-test-"
}
`

const testAccAWSCloudWatchLogGroup_generatedName = `
resource "aws_cloudwatch_log_group" "test" {}
`
20 changes: 20 additions & 0 deletions builtin/providers/aws/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,26 @@ func validateLogGroupName(v interface{}, k string) (ws []string, errors []error)
return
}

func validateLogGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

if len(value) > 483 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 483 characters: %q", k, value))
}

// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html
pattern := `^[\.\-_/#A-Za-z0-9]+$`
if !regexp.MustCompile(pattern).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q isn't a valid log group name (alphanumeric characters, underscores,"+
" hyphens, slashes, hash signs and dots are allowed): %q",
k, value))
}

return
}

func validateS3BucketLifecycleTimestamp(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
_, err := time.Parse(time.RFC3339, fmt.Sprintf("%sT00:00:00Z", value))
Expand Down
39 changes: 37 additions & 2 deletions builtin/providers/aws/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func TestValidateLogGroupName(t *testing.T) {
for _, v := range validNames {
_, errors := validateLogGroupName(v, "name")
if len(errors) != 0 {
t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors)
t.Fatalf("%q should be a valid Log Group name: %q", v, errors)
}
}

Expand All @@ -427,7 +427,42 @@ func TestValidateLogGroupName(t *testing.T) {
for _, v := range invalidNames {
_, errors := validateLogGroupName(v, "name")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v)
t.Fatalf("%q should be an invalid Log Group name", v)
}
}
}

func TestValidateLogGroupNamePrefix(t *testing.T) {
validNames := []string{
"ValidLogGroupName",
"ValidLogGroup.Name",
"valid/Log-group",
"1234",
"YadaValid#0123",
"Also_valid-name",
strings.Repeat("W", 483),
}
for _, v := range validNames {
_, errors := validateLogGroupNamePrefix(v, "name_prefix")
if len(errors) != 0 {
t.Fatalf("%q should be a valid Log Group name prefix: %q", v, errors)
}
}

invalidNames := []string{
"Here is a name with: colon",
"and here is another * invalid name",
"also $ invalid",
"This . is also %% invalid@!)+(",
"*",
"",
// length > 483
strings.Repeat("W", 484),
}
for _, v := range invalidNames {
_, errors := validateLogGroupNamePrefix(v, "name_prefix")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid Log Group name prefix", v)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ resource "aws_cloudwatch_log_group" "yada" {

The following arguments are supported:

* `name` - (Required) The name of the log group
* `name` - (Optional, Forces new resource) The name of the log group. If omitted, Terraform will assign a random, unique name.
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
* `retention_in_days` - (Optional) Specifies the number of days
you want to retain log events in the specified log group.
* `tags` - (Optional) A mapping of tags to assign to the resource.
Expand All @@ -45,4 +46,4 @@ Cloudwatch Log Groups can be imported using the `name`, e.g.

```
$ terraform import aws_cloudwatch_log_group.test_group yada
```
```