-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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: azure_consumption_budget_*
#9201
Conversation
website/azurerm.erb
Outdated
@@ -1248,6 +1248,15 @@ | |||
</ul> | |||
</li> | |||
|
|||
<li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to generate these sections via make
? I did this one manually and it appeared on make website
@@ -0,0 +1,178 @@ | |||
--- | |||
subcategory: "Consumption" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a Consumption
subcategory based on API spec, it could also go under the existing Cost Management
subcategory as well based on the goal of budgets
Will this be merged at some point? |
@sebastianreloaded this PR should be updated to the new service layout and testing structure based on the changes that have happened since this PR was originally opened as it is greenfield. I'll try to take a look at updating this PR early next week with those changes and work with the maintainers to get this PR merged in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @marc-sensenich! Thanks for your patience here! I've given it a cursory look and things look generally good! It's just a bit behind (through no fault of your own) so I haven't been able to extensively test it yet. Do you mind addressing what I've called out and bringing it back up to date.
Once that's done, I can give it another review to confirm everything is in place. If everything looks good, we can get it merged quickly.
|
||
func FlattenConsumptionBudgetNotifications(input map[string]*consumption.Notification) []interface{} { | ||
if input == nil { | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes we get weird diffing when returning nil in flatten methods so we'd rather return an empty []interface{}{}
for _, v := range input { | ||
notificationBlock := make(map[string]interface{}) | ||
|
||
notificationBlock["enabled"] = *v.Enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make sure this isn't nil before pointing to it
notifications := make(map[string]*consumption.Notification) | ||
|
||
for _, v := range input { | ||
notificationRaw := v.(map[string]interface{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll want to make sure that v isn't nil before casting to map[string]interface{}
amount := decimal.NewFromFloat(d.Get("amount").(float64)) | ||
timePeriod, err := ExpandConsumptionBudgetTimePeriod(d.Get("time_period").([]interface{})) | ||
if err != nil { | ||
return fmt.Errorf("error in expanding`time_period`: %+v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return fmt.Errorf("error in expanding`time_period`: %+v", err) | |
return fmt.Errorf("error expanding`time_period`: %+v", err) |
return err | ||
} | ||
|
||
if read.ID == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than setting the ID through this check. We've been generating the ID and then setting that. That lets us avoid issues where ID is nil.
ValidateFunc: validation.FloatAtLeast(1.0), | ||
}, | ||
|
||
"category": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know if there is plan to expand values that are accepted here? If not, we can leave it out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have insight into if this will be expanded, I added it for completeness just in case. If preferred, I'll remove it from the code path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go ahead and remove it since only one value can be specified. We can add it back in later if more categories get added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed in 25e2561
} | ||
|
||
func ExpandConsumptionBudgetComparisonExpression(input interface{}) *consumption.BudgetComparisonExpression { | ||
v := input.(map[string]interface{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll want to confirm that v isn't nil before casting.
} | ||
|
||
// DiffSuppressFuncs | ||
func DiffSuppressFuncConsumptionBudgetTimePeriodEndDate(k, old, new string, d *schema.ResourceData) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be mistaken but I thought having Computed: true
on end_date
would catch this. Is that not the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll need to double check this as I can't recall now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You were right, I can't recall exactly why I felt this was needed at the time or if it was a user error. Refactored out in 7da9f12
) | ||
|
||
const ( | ||
consumptionBudgetResourceGroupName = "azurerm_consumption_budget_resource_group" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels weird to use this format but I can see the value after thinking it through. Do you mind leaving a comment about why we're using this format in case we come back and forget why it's done this way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mbfrahry when you say "format" do you mean the actual resource name of azurerm_consumption_budget_$RESOURCE_TYPE
? I usually have a tendency to be a bit verbose with naming, so if azurerm_budget_$RESOURCE_TYPE
makes more sense it is cleaner and I can also refactor ConsumptionBudget
to Budget
in the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the added confusion. Normally we don't call out resource names into their own variables but there is a use case here because of how you're passing the names along in various methods throughout this package. I just want us to call out that in a comment so we don't forget why we're doing this differently than every other package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarification added in 2a6d556
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things are looking good! I just have concerns about the way we're doing ResourceIDs. Please let me know if what I'm suggesting makes sense!
|
||
d.Set("name", resp.Name) | ||
d.Set("category", resp.Category) | ||
amount, _ := resp.Amount.Float64() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this could panic if the value is nil
for whatever reason. Let's check that it isn't nil just to be sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nil checked in 926f618
Update: resourceArmConsumptionBudgetResourceGroupCreateUpdate, | ||
Delete: resourceArmConsumptionBudgetDelete, | ||
Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { | ||
_, err := parse.ConsumptionBudgetID(id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have concerns with this generic ConsumptionBudgetID
. Someone could pass any consumption budget id as if it was a Consumption Budget ResourceGroup and Terraform would manage it. I saw that in the id tests, you were testing various consumption budget ids from different resources. I'd like to see that expanded out so we have ConsumptionBudgetResourceGroupID
so we have 100% certainty that the resource is in fact a Consumption Budget Resource Group. Do you think that's possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good call out and for details I pass in the the various consumption budget IDs to test the ID across the 8 various scopes that a budget could be applied to. I do believe it's possible to expand these out into per consumption budget scope ID structs with a generator. My thought process is to make a generator for Consumption Budget ID structs that will generate the code for each ID and it could leverage existing validators to verify that that scope provided is in the format expected for that ID type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That ID path you laid out sounds great! Have you seen how we generate IDs in other services? Do you think a format like this could be used for Consumption Budget? Hopefully it won't be anymore issue then that for generating the ids.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mbfrahry I was able to use the available resource ID generator for this as the new features that have been added since my initial opening of this PR now support resource IDs such as the ones for Consumption Budgets. Thanks for pointing them out!
These were used with the AzureRM Consumption Budget 2019-01-01 API and are no longer required
…up Consumption Budget
…date is computed Remove DiffSuppressFuncConsumptionBudgetTimePeriodEndDate as the end_date is computed due to the Azure RM API setting this to be 10 years in the future from start_date if not specified in the config.
This is due to these being passed into generic Consumption Budget functions containing the core logic for Consumption Budget resources
…mount on resource read
…up Consumption Budget
Now that the resource ID generator supports IDs with nested resources, leverage this for generating Consumption Budget resource IDs over a custom implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I went ahead and changed the way we grab the scope for the delete methods because we really shouldn't do d.Get
inside of delete methods because it may have been removed from the statefile and the config file so we won't know what that value is. I went ahead and got the scope from the id (exactly the way you did it in the Read methods).
Other than that we're good to go! Thank you for getting this done!
azure_consumption_budget_*
This has been released in version 2.59.0 of the provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. As an example: provider "azurerm" {
version = "~> 2.59.0"
}
# ... other configuration ... |
@mbfrahry thanks for the details, cleanup, and review! |
Hilp |
…m_consumption_budget_subscription` hashicorp#9201
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions. |
Adds resources
azurerm_consumption_budget_subscription
azurerm_consumption_budget_resource_group
Test status as of 60f9fd3
Closes #2677