From ccec080e3ad2bbb59c84a8aa1a2e91033ae18a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Fri, 20 Sep 2024 06:15:36 +0200 Subject: [PATCH] New Resource: `azurerm_advisor_suppression` (#26177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * New Resource: `azurerm_advisor_suppression` * Register service in SupportedTypedServices * apply fixes from review Signed-off-by: Jan-Otto Kröpke * go mod vendor && go mod tidy --------- Signed-off-by: Jan-Otto Kröpke Co-authored-by: kt --- .github/labeler-issue-triage.yml | 2 +- internal/provider/services.go | 1 + .../advisor/advisor_suppression_resource.go | 179 ++++++++++++++++++ .../advisor_suppression_resource_test.go | 72 +++++++ internal/services/advisor/client/client.go | 11 +- internal/services/advisor/registration.go | 17 +- .../services/advisor/validate/duration.go | 19 ++ .../advisor/2023-01-01/suppressions/README.md | 91 +++++++++ .../advisor/2023-01-01/suppressions/client.go | 26 +++ .../suppressions/id_scopedsuppression.go | 129 +++++++++++++ .../2023-01-01/suppressions/method_create.go | 58 ++++++ .../2023-01-01/suppressions/method_delete.go | 46 +++++ .../2023-01-01/suppressions/method_get.go | 54 ++++++ .../2023-01-01/suppressions/method_list.go | 134 +++++++++++++ .../suppressions/model_suppressioncontract.go | 16 ++ .../model_suppressionproperties.go | 28 +++ .../2023-01-01/suppressions/predicates.go | 27 +++ .../2023-01-01/suppressions/version.go | 12 ++ vendor/modules.txt | 1 + .../docs/r/advisor_suppresion.html.markdown | 69 +++++++ 20 files changed, 989 insertions(+), 3 deletions(-) create mode 100644 internal/services/advisor/advisor_suppression_resource.go create mode 100644 internal/services/advisor/advisor_suppression_resource_test.go create mode 100644 internal/services/advisor/validate/duration.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/README.md create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/client.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/id_scopedsuppression.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_create.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_delete.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_get.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_list.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressioncontract.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressionproperties.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/predicates.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/version.go create mode 100644 website/docs/r/advisor_suppresion.html.markdown diff --git a/.github/labeler-issue-triage.yml b/.github/labeler-issue-triage.yml index 23e80e3f8391..b63e12b40d7b 100644 --- a/.github/labeler-issue-triage.yml +++ b/.github/labeler-issue-triage.yml @@ -15,7 +15,7 @@ service/aadb2c: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_aadb2c_directory((.|\n)*)###' service/advisor: - - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_advisor_recommendations((.|\n)*)###' + - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_advisor_((.|\n)*)###' service/analysis: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_analysis_services_server((.|\n)*)###' diff --git a/internal/provider/services.go b/internal/provider/services.go index 97bdf05dfc18..e350c7df91e7 100644 --- a/internal/provider/services.go +++ b/internal/provider/services.go @@ -143,6 +143,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration { authorization.Registration{}, automanage.Registration{}, automation.Registration{}, + advisor.Registration{}, azurestackhci.Registration{}, batch.Registration{}, bot.Registration{}, diff --git a/internal/services/advisor/advisor_suppression_resource.go b/internal/services/advisor/advisor_suppression_resource.go new file mode 100644 index 000000000000..600381ae97b1 --- /dev/null +++ b/internal/services/advisor/advisor_suppression_resource.go @@ -0,0 +1,179 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package advisor + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/advisor/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +var _ sdk.Resource = AdvisorSuppressionResource{} + +type AdvisorSuppressionResource struct{} + +type AdvisorSuppressionResourceModel struct { + Name string `tfschema:"name"` + SuppressionID string `tfschema:"suppression_id"` + RecommendationID string `tfschema:"recommendation_id"` + ResourceID string `tfschema:"resource_id"` + TTL string `tfschema:"ttl"` +} + +func (AdvisorSuppressionResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + "recommendation_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + "resource_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + "ttl": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.Duration, + }, + } +} + +func (AdvisorSuppressionResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "suppression_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + } +} + +func (AdvisorSuppressionResource) ModelObject() interface{} { + return &AdvisorSuppressionResourceModel{} +} + +func (AdvisorSuppressionResource) ResourceType() string { + return "azurerm_advisor_suppression" +} + +func (r AdvisorSuppressionResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Advisor.SuppressionsClient + + var model AdvisorSuppressionResourceModel + + if err := metadata.Decode(&model); err != nil { + return err + } + + id := suppressions.NewScopedSuppressionID(model.ResourceID, model.RecommendationID, model.Name) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + param := suppressions.SuppressionContract{ + Name: pointer.To(model.Name), + Properties: &suppressions.SuppressionProperties{ + SuppressionId: pointer.To(model.SuppressionID), + }, + } + + if model.TTL != "" { + param.Properties.Ttl = pointer.To(model.TTL) + } + + if _, err := client.Create(ctx, id, param); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (AdvisorSuppressionResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Advisor.SuppressionsClient + + state := AdvisorSuppressionResourceModel{} + + id, err := suppressions.ParseScopedSuppressionID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + state.Name = id.SuppressionName + state.ResourceID = id.ResourceUri + state.RecommendationID = id.RecommendationId + + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + state.TTL = pointer.From(props.Ttl) + state.SuppressionID = pointer.From(props.SuppressionId) + } + } + + return metadata.Encode(&state) + }, + } +} + +func (AdvisorSuppressionResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Advisor.SuppressionsClient + + id, err := suppressions.ParseScopedSuppressionID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if _, err := client.Delete(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} + +func (AdvisorSuppressionResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return suppressions.ValidateScopedSuppressionID +} diff --git a/internal/services/advisor/advisor_suppression_resource_test.go b/internal/services/advisor/advisor_suppression_resource_test.go new file mode 100644 index 000000000000..2edd06996697 --- /dev/null +++ b/internal/services/advisor/advisor_suppression_resource_test.go @@ -0,0 +1,72 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package advisor_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions" + "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" +) + +type AdvisorSuppressionResource struct{} + +func TestAccAnalysisServicesServer_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_advisor_suppression", "test") + r := AdvisorSuppressionResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (AdvisorSuppressionResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := suppressions.ParseScopedSuppressionID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Advisor.SuppressionsClient.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) + } + + return pointer.To(resp.Model != nil && resp.Model.Id != nil), nil +} + +func (t AdvisorSuppressionResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} + +data "azurerm_advisor_recommendations" "test" {} + +# The recommendation_names local variable is used to sort the recommendation names. +locals { + recommendation_names = sort(data.azurerm_advisor_recommendations.test.recommendations[*].recommendation_name) +} + +resource "azurerm_advisor_suppression" "test" { + name = "acctest%d" + recommendation_id = local.recommendation_names[0] + resource_id = "/subscriptions/${data.azurerm_client_config.current.subscription_id}" + ttl = "00:30:00" +} +`, data.RandomInteger) +} diff --git a/internal/services/advisor/client/client.go b/internal/services/advisor/client/client.go index 5ecfa8308ba2..30287025ec69 100644 --- a/internal/services/advisor/client/client.go +++ b/internal/services/advisor/client/client.go @@ -7,21 +7,30 @@ import ( "fmt" "github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/getrecommendations" + "github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions" "github.com/hashicorp/terraform-provider-azurerm/internal/common" ) type Client struct { RecommendationsClient *getrecommendations.GetRecommendationsClient + SuppressionsClient *suppressions.SuppressionsClient } func NewClient(o *common.ClientOptions) (*Client, error) { recommendationsClient, err := getrecommendations.NewGetRecommendationsClientWithBaseURI(o.Environment.ResourceManager) if err != nil { - return nil, fmt.Errorf("building Recommendations client: %+v", err) + return nil, fmt.Errorf("building recommendations client: %+v", err) } o.Configure(recommendationsClient.Client, o.Authorizers.ResourceManager) + suppressionsClient, err := suppressions.NewSuppressionsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("building suppressions client: %+v", err) + } + o.Configure(suppressionsClient.Client, o.Authorizers.ResourceManager) + return &Client{ RecommendationsClient: recommendationsClient, + SuppressionsClient: suppressionsClient, }, nil } diff --git a/internal/services/advisor/registration.go b/internal/services/advisor/registration.go index e6aeffa59df6..1fee463358ad 100644 --- a/internal/services/advisor/registration.go +++ b/internal/services/advisor/registration.go @@ -10,7 +10,10 @@ import ( type Registration struct{} -var _ sdk.UntypedServiceRegistrationWithAGitHubLabel = Registration{} +var ( + _ sdk.TypedServiceRegistrationWithAGitHubLabel = Registration{} + _ sdk.UntypedServiceRegistrationWithAGitHubLabel = Registration{} +) func (r Registration) AssociatedGitHubLabel() string { return "service/advisor" @@ -39,3 +42,15 @@ func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{} } + +// DataSources returns a list of Data Sources supported by this Service +func (r Registration) DataSources() []sdk.DataSource { + return []sdk.DataSource{} +} + +// Resources returns a list of Resources supported by this Service +func (r Registration) Resources() []sdk.Resource { + return []sdk.Resource{ + AdvisorSuppressionResource{}, + } +} diff --git a/internal/services/advisor/validate/duration.go b/internal/services/advisor/validate/duration.go new file mode 100644 index 000000000000..3c4af0dffbaf --- /dev/null +++ b/internal/services/advisor/validate/duration.go @@ -0,0 +1,19 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package validate + +import ( + "fmt" + "regexp" +) + +func Duration(v interface{}, k string) (warnings []string, errors []error) { + value := v.(string) + + if !regexp.MustCompile(`^(?:[0-9]{1,2}:)?[0-9]{2}:[0-9]{2}:[0-9]{2}$`).Match([]byte(value)) { + errors = append(errors, fmt.Errorf("%q must be in format DD:HH:MM:SS. If DD is 00, it has to be omit", k)) + } + + return warnings, errors +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/README.md new file mode 100644 index 000000000000..e2fad2494c15 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/README.md @@ -0,0 +1,91 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions` Documentation + +The `suppressions` SDK allows for interaction with the Azure Resource Manager Service `advisor` (API Version `2023-01-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +import "github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions" +``` + + +### Client Initialization + +```go +client := suppressions.NewSuppressionsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `SuppressionsClient.Create` + +```go +ctx := context.TODO() +id := suppressions.NewScopedSuppressionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "recommendationIdValue", "suppressionValue") + +payload := suppressions.SuppressionContract{ + // ... +} + + +read, err := client.Create(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `SuppressionsClient.Delete` + +```go +ctx := context.TODO() +id := suppressions.NewScopedSuppressionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "recommendationIdValue", "suppressionValue") + +read, err := client.Delete(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `SuppressionsClient.Get` + +```go +ctx := context.TODO() +id := suppressions.NewScopedSuppressionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "recommendationIdValue", "suppressionValue") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `SuppressionsClient.List` + +```go +ctx := context.TODO() +id := commonids.NewSubscriptionID("12345678-1234-9876-4563-123456789012") + +// alternatively `client.List(ctx, id, suppressions.DefaultListOperationOptions())` can be used to do batched pagination +items, err := client.ListComplete(ctx, id, suppressions.DefaultListOperationOptions()) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/client.go new file mode 100644 index 000000000000..61c5460e23c9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/client.go @@ -0,0 +1,26 @@ +package suppressions + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SuppressionsClient struct { + Client *resourcemanager.Client +} + +func NewSuppressionsClientWithBaseURI(sdkApi sdkEnv.Api) (*SuppressionsClient, error) { + client, err := resourcemanager.NewResourceManagerClient(sdkApi, "suppressions", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating SuppressionsClient: %+v", err) + } + + return &SuppressionsClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/id_scopedsuppression.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/id_scopedsuppression.go new file mode 100644 index 000000000000..5c91856b85f0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/id_scopedsuppression.go @@ -0,0 +1,129 @@ +package suppressions + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/recaser" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +func init() { + recaser.RegisterResourceId(&ScopedSuppressionId{}) +} + +var _ resourceids.ResourceId = &ScopedSuppressionId{} + +// ScopedSuppressionId is a struct representing the Resource ID for a Scoped Suppression +type ScopedSuppressionId struct { + ResourceUri string + RecommendationId string + SuppressionName string +} + +// NewScopedSuppressionID returns a new ScopedSuppressionId struct +func NewScopedSuppressionID(resourceUri string, recommendationId string, suppressionName string) ScopedSuppressionId { + return ScopedSuppressionId{ + ResourceUri: resourceUri, + RecommendationId: recommendationId, + SuppressionName: suppressionName, + } +} + +// ParseScopedSuppressionID parses 'input' into a ScopedSuppressionId +func ParseScopedSuppressionID(input string) (*ScopedSuppressionId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedSuppressionId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedSuppressionId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseScopedSuppressionIDInsensitively parses 'input' case-insensitively into a ScopedSuppressionId +// note: this method should only be used for API response data and not user input +func ParseScopedSuppressionIDInsensitively(input string) (*ScopedSuppressionId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedSuppressionId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedSuppressionId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ScopedSuppressionId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.ResourceUri, ok = input.Parsed["resourceUri"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "resourceUri", input) + } + + if id.RecommendationId, ok = input.Parsed["recommendationId"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "recommendationId", input) + } + + if id.SuppressionName, ok = input.Parsed["suppressionName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "suppressionName", input) + } + + return nil +} + +// ValidateScopedSuppressionID checks that 'input' can be parsed as a Scoped Suppression ID +func ValidateScopedSuppressionID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseScopedSuppressionID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Scoped Suppression ID +func (id ScopedSuppressionId) ID() string { + fmtString := "/%s/providers/Microsoft.Advisor/recommendations/%s/suppressions/%s" + return fmt.Sprintf(fmtString, strings.TrimPrefix(id.ResourceUri, "/"), id.RecommendationId, id.SuppressionName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Scoped Suppression ID +func (id ScopedSuppressionId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("resourceUri", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftAdvisor", "Microsoft.Advisor", "Microsoft.Advisor"), + resourceids.StaticSegment("staticRecommendations", "recommendations", "recommendations"), + resourceids.UserSpecifiedSegment("recommendationId", "recommendationIdValue"), + resourceids.StaticSegment("staticSuppressions", "suppressions", "suppressions"), + resourceids.UserSpecifiedSegment("suppressionName", "suppressionValue"), + } +} + +// String returns a human-readable description of this Scoped Suppression ID +func (id ScopedSuppressionId) String() string { + components := []string{ + fmt.Sprintf("Resource Uri: %q", id.ResourceUri), + fmt.Sprintf("Recommendation: %q", id.RecommendationId), + fmt.Sprintf("Suppression Name: %q", id.SuppressionName), + } + return fmt.Sprintf("Scoped Suppression (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_create.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_create.go new file mode 100644 index 000000000000..29c5ccab0a34 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_create.go @@ -0,0 +1,58 @@ +package suppressions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *SuppressionContract +} + +// Create ... +func (c SuppressionsClient) Create(ctx context.Context, id ScopedSuppressionId, input SuppressionContract) (result CreateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model SuppressionContract + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_delete.go new file mode 100644 index 000000000000..2b8f8994350c --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_delete.go @@ -0,0 +1,46 @@ +package suppressions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData +} + +// Delete ... +func (c SuppressionsClient) Delete(ctx context.Context, id ScopedSuppressionId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusNoContent, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_get.go new file mode 100644 index 000000000000..183b07ea15a4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_get.go @@ -0,0 +1,54 @@ +package suppressions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *SuppressionContract +} + +// Get ... +func (c SuppressionsClient) Get(ctx context.Context, id ScopedSuppressionId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model SuppressionContract + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_list.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_list.go new file mode 100644 index 000000000000..91e057e4ba86 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/method_list.go @@ -0,0 +1,134 @@ +package suppressions + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]SuppressionContract +} + +type ListCompleteResult struct { + LatestHttpResponse *http.Response + Items []SuppressionContract +} + +type ListOperationOptions struct { + Top *int64 +} + +func DefaultListOperationOptions() ListOperationOptions { + return ListOperationOptions{} +} + +func (o ListOperationOptions) ToHeaders() *client.Headers { + out := client.Headers{} + + return &out +} + +func (o ListOperationOptions) ToOData() *odata.Query { + out := odata.Query{} + return &out +} + +func (o ListOperationOptions) ToQuery() *client.QueryParams { + out := client.QueryParams{} + if o.Top != nil { + out.Append("$top", fmt.Sprintf("%v", *o.Top)) + } + return &out +} + +type ListCustomPager struct { + NextLink *odata.Link `json:"nextLink"` +} + +func (p *ListCustomPager) NextPageLink() *odata.Link { + defer func() { + p.NextLink = nil + }() + + return p.NextLink +} + +// List ... +func (c SuppressionsClient) List(ctx context.Context, id commonids.SubscriptionId, options ListOperationOptions) (result ListOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + OptionsObject: options, + Pager: &ListCustomPager{}, + Path: fmt.Sprintf("%s/providers/Microsoft.Advisor/suppressions", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]SuppressionContract `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListComplete retrieves all the results into a single object +func (c SuppressionsClient) ListComplete(ctx context.Context, id commonids.SubscriptionId, options ListOperationOptions) (ListCompleteResult, error) { + return c.ListCompleteMatchingPredicate(ctx, id, options, SuppressionContractOperationPredicate{}) +} + +// ListCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c SuppressionsClient) ListCompleteMatchingPredicate(ctx context.Context, id commonids.SubscriptionId, options ListOperationOptions, predicate SuppressionContractOperationPredicate) (result ListCompleteResult, err error) { + items := make([]SuppressionContract, 0) + + resp, err := c.List(ctx, id, options) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressioncontract.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressioncontract.go new file mode 100644 index 000000000000..3941e882d355 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressioncontract.go @@ -0,0 +1,16 @@ +package suppressions + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/systemdata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SuppressionContract struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *SuppressionProperties `json:"properties,omitempty"` + SystemData *systemdata.SystemData `json:"systemData,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressionproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressionproperties.go new file mode 100644 index 000000000000..f7bebedb5045 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/model_suppressionproperties.go @@ -0,0 +1,28 @@ +package suppressions + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/lang/dates" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SuppressionProperties struct { + ExpirationTimeStamp *string `json:"expirationTimeStamp,omitempty"` + SuppressionId *string `json:"suppressionId,omitempty"` + Ttl *string `json:"ttl,omitempty"` +} + +func (o *SuppressionProperties) GetExpirationTimeStampAsTime() (*time.Time, error) { + if o.ExpirationTimeStamp == nil { + return nil, nil + } + return dates.ParseAsFormat(o.ExpirationTimeStamp, "2006-01-02T15:04:05Z07:00") +} + +func (o *SuppressionProperties) SetExpirationTimeStampAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.ExpirationTimeStamp = &formatted +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/predicates.go new file mode 100644 index 000000000000..4e0826acb8d2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/predicates.go @@ -0,0 +1,27 @@ +package suppressions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SuppressionContractOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p SuppressionContractOperationPredicate) Matches(input SuppressionContract) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/version.go new file mode 100644 index 000000000000..9a185f5807ad --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions/version.go @@ -0,0 +1,12 @@ +package suppressions + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2023-01-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/suppressions/%s", defaultApiVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 3a24d5e8e5de..6aa9f418af97 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -154,6 +154,7 @@ github.com/hashicorp/go-azure-sdk/resource-manager/aad/2021-05-01/domainservices github.com/hashicorp/go-azure-sdk/resource-manager/aadb2c/2021-04-01-preview github.com/hashicorp/go-azure-sdk/resource-manager/aadb2c/2021-04-01-preview/tenants github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/getrecommendations +github.com/hashicorp/go-azure-sdk/resource-manager/advisor/2023-01-01/suppressions github.com/hashicorp/go-azure-sdk/resource-manager/alertsmanagement/2019-06-01/smartdetectoralertrules github.com/hashicorp/go-azure-sdk/resource-manager/alertsmanagement/2021-08-08/alertprocessingrules github.com/hashicorp/go-azure-sdk/resource-manager/alertsmanagement/2023-03-01/prometheusrulegroups diff --git a/website/docs/r/advisor_suppresion.html.markdown b/website/docs/r/advisor_suppresion.html.markdown new file mode 100644 index 000000000000..eaf9f31358f2 --- /dev/null +++ b/website/docs/r/advisor_suppresion.html.markdown @@ -0,0 +1,69 @@ +--- +subcategory: "Advisor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_advisor_suppression" +description: |- + Specifies a suppression for an Azure Advisor recommendation. +--- + +# azurerm_advisor_suppression + +Specifies a suppression for an Azure Advisor recommendation. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} + +data "azurerm_advisor_recommendations" "example" {} + +resource "azurerm_advisor_suppression" "example" { + name = "HardcodedSuppressionName" + recommendation_id = data.azurerm_advisor_recommendations.test.recommendations[0].recommendation_name + resource_id = "/subscriptions/${data.azurerm_client_config.current.subscription_id}" + ttl = "01:00:00:00" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The Name which should be used for this Advisor suppression. Changing this forces a new Advisor suppression to be created. + +* `recommendation_id` - (Required) The ID of the Advisor recommendation to suppress. Changing this forces a new Advisor suppression to be created. + +* `resource_id` - (Required) The ID of the Resource to suppress the Advisor recommendation for. Changing this forces a new Advisor suppression to be created. + +--- + +* `ttl` - (Optional) A optional time to live value. If omitted, the suppression will not expire. Changing this forces a new Advisor suppression to be created. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Advisor suppression. + +* `suppression_id` - The GUID of the suppression. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Advisor suppression. +* `read` - (Defaults to 5 minutes) Used when retrieving the Advisor suppression. +* `update` - (Defaults to 30 minutes) Used when updating the Advisor suppression. +* `delete` - (Defaults to 30 minutes) Used when deleting the Advisor suppression. + +## Import + +Advisor suppressions can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_advisor_suppression.example /subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Advisor/recommendations/00000000-0000-0000-0000-000000000000/suppressions/name +```