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

New resource: azurerm_log_analytics_workspace_table #24229

Merged
merged 1 commit into from
Dec 18, 2023
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
9 changes: 9 additions & 0 deletions internal/services/loganalytics/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/savedsearches"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/storageinsights"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/workspaces"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2022-10-01/tables"
featureWorkspaces "github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2022-10-01/workspaces"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationsmanagement/2015-11-01-preview/solution"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
Expand All @@ -33,6 +34,7 @@ type Client struct {
StorageInsightsClient *storageinsights.StorageInsightsClient
QueryPackQueriesClient *querypackqueries.QueryPackQueriesClient
SharedKeyWorkspacesClient *workspaces.WorkspacesClient
TablesClient *tables.TablesClient
WorkspaceClient *featureWorkspaces.WorkspacesClient // 2022-10-01 API version does not contain sharedkeys related API, so we keep two versions SDK of this API
}

Expand Down Expand Up @@ -109,6 +111,12 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(queryPackQueriesClient.Client, o.Authorizers.ResourceManager)

tablesClient, err := tables.NewTablesClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Tables client: %+v", err)
}
o.Configure(tablesClient.Client, o.Authorizers.ResourceManager)

return &Client{
ClusterClient: clusterClient,
DataExportClient: dataExportClient,
Expand All @@ -121,6 +129,7 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
SolutionsClient: solutionsClient,
StorageInsightsClient: storageInsightsClient,
SharedKeyWorkspacesClient: workspacesClient,
TablesClient: tablesClient,
WorkspaceClient: featureWorkspaceClient,
}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
package loganalytics

import (
"context"
"fmt"
"log"
"time"

"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2022-10-01/tables"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2022-10-01/workspaces"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type LogAnalyticsWorkspaceTableResource struct {
}

var _ sdk.ResourceWithUpdate = LogAnalyticsWorkspaceTableResource{}

type LogAnalyticsWorkspaceTableResourceModel struct {
Name string `tfschema:"name"`
WorkspaceId string `tfschema:"workspace_id"`
RetentionInDays int64 `tfschema:"retention_in_days"`
}

func (r LogAnalyticsWorkspaceTableResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"workspace_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: workspaces.ValidateWorkspaceID,
},

"name": {
Type: pluginsdk.TypeString,
Required: true,
},

"retention_in_days": {
Type: pluginsdk.TypeInt,
Required: true,
ValidateFunc: validation.Any(validation.IntBetween(30, 730), validation.IntInSlice([]int{7})),
},
}
}

func (r LogAnalyticsWorkspaceTableResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{}
}

func (r LogAnalyticsWorkspaceTableResource) ModelObject() interface{} {
return &LogAnalyticsWorkspaceTableResourceModel{}
}

func (r LogAnalyticsWorkspaceTableResource) ResourceType() string {
return "azurerm_log_analytics_workspace_table"
}

func (r LogAnalyticsWorkspaceTableResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return tables.ValidateTableID
}

func (r LogAnalyticsWorkspaceTableResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model LogAnalyticsWorkspaceTableResourceModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding %+v", err)
}
client := metadata.Client.LogAnalytics.TablesClient
subscriptionId := metadata.Client.Account.SubscriptionId

tableName := model.Name
log.Printf("[INFO] preparing arguments for AzureRM Log Analytics Workspace Table %s update.", tableName)

workspaceId, err := workspaces.ParseWorkspaceID(model.WorkspaceId)
if err != nil {
return fmt.Errorf("invalid workspace object ID for table %s: %s", tableName, err)
}

id := tables.NewTableID(subscriptionId, workspaceId.ResourceGroupName, workspaceId.WorkspaceName, tableName)

retentionInDays := model.RetentionInDays
updateInput := tables.Table{
Properties: &tables.TableProperties{
RetentionInDays: &retentionInDays,
},
}
if err := client.CreateOrUpdateThenPoll(ctx, id, updateInput); err != nil {
return fmt.Errorf("failed to update table %s in workspace %s in resource group %s: %s", tableName, workspaceId.WorkspaceName, workspaceId.ResourceGroupName, err)
}

metadata.SetID(id)
return nil
},
}
}

func (r LogAnalyticsWorkspaceTableResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.LogAnalytics.TablesClient
id, err := tables.ParseTableID(metadata.ResourceData.Id())
if err != nil {
return err
}

var state LogAnalyticsWorkspaceTableResourceModel
if err := metadata.Decode(&state); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

existing, err := client.Get(ctx, *id)
if err != nil {
return fmt.Errorf("reading Log Analytics Workspace Table %s: %v", id, err)
}

updateInput := tables.Table{
Properties: &tables.TableProperties{
RetentionInDays: existing.Model.Properties.RetentionInDays,
},
}

if metadata.ResourceData.HasChange("retention_in_days") {
updateInput.Properties.RetentionInDays = &state.RetentionInDays
}
if err := client.CreateOrUpdateThenPoll(ctx, *id, updateInput); err != nil {
return fmt.Errorf("failed to update table: %s: %+v", id.TableName, err)
}

return nil
},
}
}

func (r LogAnalyticsWorkspaceTableResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
id, err := tables.ParseTableID(metadata.ResourceData.Id())
if err != nil {
return fmt.Errorf("while parsing resource ID: %+v", err)
}

workspaceId, err := workspaces.ParseWorkspaceID(metadata.ResourceData.Get("workspace_id").(string))
if err != nil {
return fmt.Errorf("while parsing resource ID: %+v", err)
}

client := metadata.Client.LogAnalytics.TablesClient

resp, err := client.Get(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}
return fmt.Errorf("retrieving Log Analytics Workspace Table %s: %+v", *id, err)
}

state := LogAnalyticsWorkspaceTableResourceModel{
Name: id.TableName,
WorkspaceId: workspaceId.ID(),
}

if model := resp.Model; model != nil {
if model.Properties.RetentionInDays != nil {
state.RetentionInDays = *model.Properties.RetentionInDays
}
}

return metadata.Encode(&state)
},
}
}

func (r LogAnalyticsWorkspaceTableResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model LogAnalyticsWorkspaceTableResourceModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding %+v", err)
}
client := metadata.Client.LogAnalytics.TablesClient
id, err := tables.ParseTableID(metadata.ResourceData.Id())
if err != nil {
return fmt.Errorf("while parsing resource ID: %+v", err)
}

// We do not delete the resource here, just set the retention to workspace default value, which is
// achieved by setting the value to `-1`
retentionInDays := utils.Int64(-1)

updateInput := tables.Table{
Properties: &tables.TableProperties{
RetentionInDays: retentionInDays,
},
}

if err := client.CreateOrUpdateThenPoll(ctx, *id, updateInput); err != nil {
return fmt.Errorf("failed to update table %s in workspace %s in resource group %s: %s", id.TableName, id.WorkspaceName, id.ResourceGroupName, err)
}

return nil
},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package loganalytics_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2022-10-01/tables"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type LogAnalyticsWorkspaceTableResource struct{}

func TestAccLogAnalyticsWorkspaceTable_updateTableRetention(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_log_analytics_workspace_table", "test")
r := LogAnalyticsWorkspaceTableResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.updateRetention(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("id").Exists(),
check.That(data.ResourceName).Key("name").HasValue("AppEvents"),
check.That(data.ResourceName).Key("retention_in_days").HasValue("7"),
),
},
})
}

func (t LogAnalyticsWorkspaceTableResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := tables.ParseTableID(state.ID)
if err != nil {
return nil, err
}

resp, err := clients.LogAnalytics.TablesClient.Get(ctx, *id)
if err != nil {
return nil, fmt.Errorf("reading Log Analytics Workspace Table (%s): %+v", id.ID(), err)
}

return utils.Bool(resp.Model.Id != nil), nil
}

func (LogAnalyticsWorkspaceTableResource) updateRetention(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_log_analytics_workspace" "test" {
name = "acctestLAW-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
retention_in_days = 30
}
resource "azurerm_log_analytics_workspace_table" "test" {
name = "AppEvents"
workspace_id = azurerm_log_analytics_workspace.test.id
retention_in_days = 7
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}
1 change: 1 addition & 0 deletions internal/services/loganalytics/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (r Registration) Resources() []sdk.Resource {
LogAnalyticsQueryPackResource{},
LogAnalyticsQueryPackQueryResource{},
LogAnalyticsSolutionResource{},
LogAnalyticsWorkspaceTableResource{},
}
}

Expand Down
Loading
Loading