Skip to content

Commit

Permalink
New Resource: azurerm_log_analytics_datasource_windows_performance_co…
Browse files Browse the repository at this point in the history
…unter #6274
  • Loading branch information
mbfrahry authored Mar 30, 2020
2 parents c7039db + c9f2e5b commit 0ee8821
Show file tree
Hide file tree
Showing 8 changed files with 660 additions and 3 deletions.
5 changes: 5 additions & 0 deletions azurerm/internal/services/loganalytics/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import (
)

type Client struct {
DataSourcesClient *operationalinsights.DataSourcesClient
LinkedServicesClient *operationalinsights.LinkedServicesClient
SolutionsClient *operationsmanagement.SolutionsClient
WorkspacesClient *operationalinsights.WorkspacesClient
}

func NewClient(o *common.ClientOptions) *Client {
DataSourcesClient := operationalinsights.NewDataSourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&DataSourcesClient.Client, o.ResourceManagerAuthorizer)

WorkspacesClient := operationalinsights.NewWorkspacesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&WorkspacesClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -23,6 +27,7 @@ func NewClient(o *common.ClientOptions) *Client {
o.ConfigureClient(&LinkedServicesClient.Client, o.ResourceManagerAuthorizer)

return &Client{
DataSourcesClient: &DataSourcesClient,
LinkedServicesClient: &LinkedServicesClient,
SolutionsClient: &SolutionsClient,
WorkspacesClient: &WorkspacesClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package parse

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type LogAnalyticsDataSourceId struct {
ResourceGroup string
Workspace string
Name string
}

func LogAnalyticsDataSourceID(input string) (*LogAnalyticsDataSourceId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("[ERROR] Unable to parse Log Analytics Data Source ID %q: %+v", input, err)
}

server := LogAnalyticsDataSourceId{
ResourceGroup: id.ResourceGroup,
}

if server.Workspace, err = id.PopSegment("workspaces"); err != nil {
return nil, err
}

if server.Name, err = id.PopSegment("datasources"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &server, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package parse

import (
"testing"
)

func TestLogAnalyticsDataSourceID(t *testing.T) {
testData := []struct {
Name string
Input string
Error bool
Expect *LogAnalyticsDataSourceId
}{
{
Name: "Empty",
Input: "",
Error: true,
},
{
Name: "No Resource Groups Segment",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000",
Error: true,
},
{
Name: "No Resource Groups Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/",
Error: true,
},
{
Name: "Resource Group ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/",
Error: true,
},
{
Name: "Missing Workspace Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces",
Error: true,
},
{
Name: "Workspace Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1",
Error: true,
},
{
Name: "Missing DataSource Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/datasources",
Error: true,
},
{
Name: "DataSource Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/datasources/datasource1",
Error: true,
Expect: &LogAnalyticsDataSourceId{
ResourceGroup: "resGroup1",
Workspace: "workspace1",
Name: "datasource1",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Name)

actual, err := LogAnalyticsDataSourceID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expected a value but got an error: %s", err)
}

if actual.ResourceGroup != v.Expect.ResourceGroup {
t.Fatalf("Expected %q but got %q for Resource Group", v.Expect.ResourceGroup, actual.ResourceGroup)
}

if actual.Workspace != v.Expect.Workspace {
t.Fatalf("Expected %q but got %q for Name", v.Expect.Workspace, actual.Workspace)
}

if actual.Name != v.Expect.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expect.Name, actual.Name)
}
}
}
8 changes: 5 additions & 3 deletions azurerm/internal/services/loganalytics/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource {
// SupportedResources returns the supported Resources supported by this Service
func (r Registration) SupportedResources() map[string]*schema.Resource {
return map[string]*schema.Resource{
"azurerm_log_analytics_linked_service": resourceArmLogAnalyticsLinkedService(),
"azurerm_log_analytics_solution": resourceArmLogAnalyticsSolution(),
"azurerm_log_analytics_workspace": resourceArmLogAnalyticsWorkspace()}
"azurerm_log_analytics_linked_service": resourceArmLogAnalyticsLinkedService(),
"azurerm_log_analytics_solution": resourceArmLogAnalyticsSolution(),
"azurerm_log_analytics_workspace": resourceArmLogAnalyticsWorkspace(),
"azurerm_log_analytics_datasource_windows_performance_counter": resourceArmLogAnalyticsDataSourceWindowsPerformanceCounter(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package loganalytics

import (
"encoding/json"
"fmt"
"log"
"math"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/operationalinsights/mgmt/2015-11-01-preview/operationalinsights"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/structure"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/parse"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmLogAnalyticsDataSourceWindowsPerformanceCounter() *schema.Resource {
return &schema.Resource{
Create: resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterCreateUpdate,
Read: resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterRead,
Update: resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterCreateUpdate,
Delete: resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterDelete,

Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := parse.LogAnalyticsDataSourceID(id)
return err
}),

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Update: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"resource_group_name": azure.SchemaResourceGroupName(),

"workspace_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: ValidateAzureRmLogAnalyticsWorkspaceName,
},

"counter_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"instance_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"interval_seconds": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(10, math.MaxInt32),
},

"object_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
}
}

type dataSourceWindowsPerformanceCounterProperty struct {
CounterName string `json:"counterName"`
InstanceName string `json:"instanceName"`
IntervalSeconds int `json:"intervalSeconds"`
ObjectName string `json:"objectName"`
}

func resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).LogAnalytics.DataSourcesClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)
resourceGroup := d.Get("resource_group_name").(string)
workspaceName := d.Get("workspace_name").(string)

if d.IsNewResource() {
resp, err := client.Get(ctx, resourceGroup, workspaceName, name)
if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("failed to check for existing Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", name, resourceGroup, workspaceName, err)
}
}

if !utils.ResponseWasNotFound(resp.Response) {
return tf.ImportAsExistsError("azurerm_log_analytics_datasource_windows_performance_counter", *resp.ID)
}
}

prop := &dataSourceWindowsPerformanceCounterProperty{
CounterName: d.Get("counter_name").(string),
InstanceName: d.Get("instance_name").(string),
IntervalSeconds: d.Get("interval_seconds").(int),
ObjectName: d.Get("object_name").(string),
}

params := operationalinsights.DataSource{
Kind: operationalinsights.WindowsPerformanceCounter,
Properties: prop,
}

if _, err := client.CreateOrUpdate(ctx, resourceGroup, workspaceName, name, params); err != nil {
return fmt.Errorf("failed to create Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", name, resourceGroup, workspaceName, err)
}

resp, err := client.Get(ctx, resourceGroup, workspaceName, name)
if err != nil {
return fmt.Errorf("failed to retrieve Log Analytics DataSource Windows Performance Counter %q (Resource Group %q): %+v", name, resourceGroup, err)
}

if resp.ID == nil || *resp.ID == "" {
return fmt.Errorf("Cannot read ID for Log Analytics DataSource Windows Performance Counter %q (Resource Group %q)", name, resourceGroup)
}

d.SetId(*resp.ID)

return resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterRead(d, meta)
}

func resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).LogAnalytics.DataSourcesClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.LogAnalyticsDataSourceID(d.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, id.ResourceGroup, id.Workspace, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] Log Analytics DataSource Windows Performance Counter %q was not found in Resource Group %q in Workspace %q - removing from state!", id.Name, id.ResourceGroup, id.Workspace)
d.SetId("")
return nil
}

return fmt.Errorf("failed to retrieve Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", id.Name, id.ResourceGroup, id.Workspace, err)
}

d.Set("name", resp.Name)
d.Set("resource_group_name", id.ResourceGroup)
d.Set("workspace_name", id.Workspace)
if props := resp.Properties; props != nil {
propStr, err := structure.FlattenJsonToString(props.(map[string]interface{}))
if err != nil {
return fmt.Errorf("failed to flatten properties map to json for Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", id.Name, id.ResourceGroup, id.Workspace, err)
}

prop := &dataSourceWindowsPerformanceCounterProperty{}
if err := json.Unmarshal([]byte(propStr), &prop); err != nil {
return fmt.Errorf("failed to decode properties json for Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", id.Name, id.ResourceGroup, id.Workspace, err)
}

d.Set("counter_name", prop.CounterName)
d.Set("instance_name", prop.InstanceName)
d.Set("interval_seconds", prop.IntervalSeconds)
d.Set("object_name", prop.ObjectName)
}

return nil
}

func resourceArmLogAnalyticsDataSourceWindowsPerformanceCounterDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).LogAnalytics.DataSourcesClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.LogAnalyticsDataSourceID(d.Id())
if err != nil {
return err
}

if _, err := client.Delete(ctx, id.ResourceGroup, id.Workspace, id.Name); err != nil {
return fmt.Errorf("failed to delete Log Analytics DataSource Windows Performance Counter %q (Resource Group %q / Workspace: %q): %+v", id.Name, id.ResourceGroup, id.Workspace, err)
}

return nil
}
Loading

0 comments on commit 0ee8821

Please sign in to comment.