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

Feature: AppDynamics data link #558

Merged
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0
github.com/mitchellh/go-homedir v1.1.0
github.com/signalfx/signalfx-go v1.43.0
github.com/signalfx/signalfx-go v1.44.0
github.com/stretchr/testify v1.10.0
go.uber.org/multierr v1.11.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEA
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/signalfx/signalfx-go v1.43.0 h1:Wp/XkyETzRyFvtuCGTN039hYwVgwIPfkBciqs19hqv4=
github.com/signalfx/signalfx-go v1.43.0/go.mod h1:I30umyhRTu8mPpEtMzEbG0z9wOYjkUKTp9U0gFxFsmk=
github.com/signalfx/signalfx-go v1.44.0 h1:BkLtohTJkq3mr1Yl1OzCWK+e2DZRqZ0M0zD9Gs+c41Q=
github.com/signalfx/signalfx-go v1.44.0/go.mod h1:I30umyhRTu8mPpEtMzEbG0z9wOYjkUKTp9U0gFxFsmk=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
57 changes: 56 additions & 1 deletion signalfx/resource_signalfx_data_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"encoding/json"
"fmt"
"log"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -128,6 +129,25 @@
},
},
},
"target_appd_url": {
Type: schema.TypeSet,
Optional: true,
Description: "Link to AppDynamics URL",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "User-assigned target name. Use this value to differentiate between the link targets for a data link object.",
},
"url": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "URL string for an AppDyanmics data link target.",
},
},
},
},
},

Create: dataLinkCreate,
Expand Down Expand Up @@ -206,6 +226,29 @@
}
}

if val, ok := d.GetOk("target_appd_url"); ok {
appdURLs := val.(*schema.Set).List()

appdUrlPatternRegex := "^https?:\\/\\/[a-zA-Z0-9-]+\\.saas\\.appdynamics\\.com\\/.*application=\\d+.*component=\\d+.*"

Check failure on line 232 in signalfx/resource_signalfx_data_link.go

View workflow job for this annotation

GitHub Actions / lint

var-naming: var appdUrlPatternRegex should be appdURLPatternRegex (revive)
re := regexp.MustCompile(appdUrlPatternRegex)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Avoid using MustCompile or Must* methods in general since on error they will panic causing state to be incorrectly set if this was to be in the middle in an apply.

Be sure to use Compile instead and return the error.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you mind expanding on what the regular expression is testing?

Reading it it looks like you can have any wildcard for *.saas.appdynamics.com and expecting to have the query values for application, and component?

Did I miss anything here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes that is correct. The other condition would be that the query values for application and component need to be positive integers.


for _, tfLink := range appdURLs {
tfLink := tfLink.(map[string]interface{})

dl := &datalink.Target{
Name: tfLink["name"].(string),
URL: tfLink["url"].(string),
Type: datalink.APPD_LINK,
}
match := re.MatchString(dl.URL)
if !match {
return dataLink, fmt.Errorf("Enter a valid AppD Link. The link needs to include the contoller URL, application ID, and Application component.")

Check failure on line 245 in signalfx/resource_signalfx_data_link.go

View workflow job for this annotation

GitHub Actions / lint

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
}

dataLink.Targets = append(dataLink.Targets, dl)
}
}

if val, ok := d.GetOk("target_external_url"); ok {
exURLs := val.(*schema.Set).List()

Expand Down Expand Up @@ -249,7 +292,7 @@
}

if len(dataLink.Targets) < 1 {
return dataLink, fmt.Errorf("You must provide one or more of `target_signalfx_dashboard`, `target_external_url`, or `target_splunk`")
return dataLink, fmt.Errorf("You must provide one or more of `target_signalfx_dashboard`, `target_external_url`, `target_appd_url` or `target_splunk`")
}

return dataLink, nil
Expand Down Expand Up @@ -290,6 +333,7 @@
var internalLinks []map[string]interface{}
var externalLinks []map[string]interface{}
var splunkLinks []map[string]interface{}
var appdLinks []map[string]interface{}

for _, t := range dl.Targets {
switch t.Type {
Expand All @@ -316,6 +360,12 @@
"property_key_mapping": t.PropertyKeyMapping,
}
splunkLinks = append(splunkLinks, tfTarget)
case datalink.APPD_LINK:
tfTarget := map[string]interface{}{
"name": t.Name,
"url": t.URL,
}
appdLinks = append(appdLinks, tfTarget)
default:
return fmt.Errorf("Unknown link type: %s", t.Type)
}
Expand All @@ -335,6 +385,11 @@
return err
}
}
if appdLinks != nil && len(appdLinks) > 0 {

Check failure on line 388 in signalfx/resource_signalfx_data_link.go

View workflow job for this annotation

GitHub Actions / lint

S1009: should omit nil check; len() for []map[string]interface{} is defined as zero (gosimple)
if err := d.Set("target_appd_url", appdLinks); err != nil {
return err
}
}

return nil
}
Expand Down
54 changes: 54 additions & 0 deletions signalfx/resource_signalfx_data_link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,30 @@
}
`

const newDataLinkAppdConfig = `
resource "signalfx_data_link" "big_test_data_link" {
property_name = "pname"
property_value = "pvalue"

target_appd_url {
name = "appd_url"
url = "https://example.saas.appdynamics.com/controller/#/application=3039831&component=3677819"
}
}
`

const newDataLinkAppdConfigBadUrlErr = `

Check failure on line 87 in signalfx/resource_signalfx_data_link_test.go

View workflow job for this annotation

GitHub Actions / lint

var-naming: const newDataLinkAppdConfigBadUrlErr should be newDataLinkAppdConfigBadURLErr (revive)
resource "signalfx_data_link" "big_test_data_link" {
property_name = "pname"
property_value = "pvalue"

target_appd_url {
name = "appd_url"
url = "https://example.saas.appdynamics.com/controller/#/application=3039831"
}
}
`

func TestAccCreateDashboardDataLinkFails(t *testing.T) {
resource.Test(t, resource.TestCase{
Providers: testAccProviders,
Expand Down Expand Up @@ -140,6 +164,36 @@
})
}

func TestAccCreateAppdDataLinkFails(t *testing.T) {
resource.Test(t, resource.TestCase{
Providers: testAccProviders,
CheckDestroy: testAccDataLinkDestroy,
Steps: []resource.TestStep{
{
Config: newDataLinkAppdConfigBadUrlErr,
ExpectError: regexp.MustCompile("Enter a valid AppD Link. The link needs to include the contoller URL, application ID, and Application component."),
},
},
})
}
func TestAccCreateAppdDataLink(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccDataLinkDestroy,
Steps: []resource.TestStep{
{
Config: newDataLinkAppdConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckDataLinkResourceExists,
resource.TestCheckResourceAttr("signalfx_data_link.big_test_data_link", "property_name", "pname"),
resource.TestCheckResourceAttr("signalfx_data_link.big_test_data_link", "property_value", "pvalue"),
),
},
},
})
}

func testDataLinkUpdated(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
switch rs.Type {
Expand Down
Loading