-
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
azurerm_windows_function_app
, azurerm_linux_function_app
- fix content share not being created automatically issue
#18258
Conversation
azurerm_windows_function_app
, azurerm_linux_function_app
: fix content share not being created automatically issue
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.
Hi @xiaxyi - Thanks for this PR.
I've left some comments inline below that will need to be addressed before we can continue review. I think this PR should probably have been split into smaller specific PRs to address the disparate concerns as the changes do not fully match the description / title, which makes the changes difficult to review and will unfortunately slow the process. That said, if you can make the changes here we can get this moving.
Thanks!
@@ -137,7 +137,7 @@ func PlanTypeFromSku(input string) string { | |||
} | |||
|
|||
// ServicePlanInfoForApp returns the OS type and Service Plan SKU for a given App Service Resource | |||
func ServicePlanInfoForApp(ctx context.Context, metadata sdk.ResourceMetaData, id interface{}) (osType *string, planSku *string, err error) { | |||
func ServicePlanInfoForApp(ctx context.Context, metadata sdk.ResourceMetaData, id interface{}, serviceFarmId string) (osType *string, planSku *string, err error) { |
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.
This function is intended to retrieve the Service Plan ID from the App ID, it should not take the ID directly to circumvent this.
// Some service plan updates are allowed - see customiseDiff for exceptions | ||
var serviceFarmId string | ||
if metadata.ResourceData.HasChange("service_plan_id") { | ||
serviceFarmId = state.ServicePlanId | ||
existing.SiteProperties.ServerFarmID = utils.String(serviceFarmId) | ||
} | ||
|
||
_, planSKU, err := helpers.ServicePlanInfoForApp(ctx, metadata, *id, serviceFarmId) |
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.
This should be a call to the new service plan to get the SKU, and not repurpose the helper function.
var storageAccountName, storageFileShare string | ||
if sendContentSettings || helpers.PlanIsConsumption(planSku) { | ||
if appSettingsResp.Properties != nil { | ||
if appSettingsResp.Properties["WEBSITE_CONTENTAZUREFILECONNECTIONSTRING"] != nil { | ||
saConnectionString := strings.Split(*appSettingsResp.Properties["WEBSITE_CONTENTAZUREFILECONNECTIONSTRING"], ";") | ||
for _, part := range saConnectionString { | ||
if strings.Contains(part, "AccountName") { | ||
storageAccountName = strings.TrimPrefix(part, "AccountName=") | ||
break | ||
} | ||
} | ||
} | ||
if appSettingsResp.Properties["WEBSITE_CONTENTSHARE"] != nil { | ||
storageFileShare = *appSettingsResp.Properties["WEBSITE_CONTENTSHARE"] | ||
} | ||
saClient := metadata.Client.Storage | ||
account, err := saClient.FindAccount(ctx, storageAccountName) | ||
if err != nil { | ||
return fmt.Errorf("retrieving Account %q for Share %q: %s", storageAccountName, storageFileShare, err) | ||
} | ||
if account == nil { | ||
return fmt.Errorf("unable to locate Storage Account %s", storageAccountName) | ||
} | ||
saFileShareClient, err := metadata.Client.Storage.FileSharesClient(ctx, *account) | ||
if err != nil { | ||
return fmt.Errorf("building File Share Client: %s", err) | ||
} | ||
exists, err := saFileShareClient.Exists(ctx, account.ResourceGroup, storageAccountName, storageFileShare) | ||
if err != nil { | ||
return fmt.Errorf("checking for existence of Storage Share %q (Account %q) : %+v", storageFileShare, storageAccountName, err) | ||
} | ||
if exists == nil { | ||
return fmt.Errorf("the storage file share %s for function app %s does not exists, please specify an existing one", storageFileShare, id.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.
As above, this shouldn't be in the Read.
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.
Thanks for the review, this is to address the timeout issue. if the user doesn't specify a predefined file share and also set the WEBSITE_CONTENTOVERVNET in the app_setting, the provider will timeout by trying to access a non-existence file share. I can add the 4.0 condition to this check block.
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.
agreed - this shouldn't be in the Read function - we don't retrieve the file share in the Read, so this is unnecessary
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.
Thanks @tombuildsstuff for the comments. If we don't check the storage file share, shall we just let the read function timeout?
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.
@xiaxyi why will the read function timeout? it's calling the App Service ARM API and not interacting with the Storage Account in the read function?
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.
The function app is trying to connect to the file share specified in the [WEBSITE_CONTENTSHARE](https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings)
, Generally, the file share is created by function app automatically, however, the it cannot be created if user specify the key WEBSITE_CONTENTOVERVNET
in app_setting, it requires the user to create a valid file share in advance and put the value in
WEBSITE_CONTENTSHARE`. We didn't add such notes to user in the current provider, so the function(Read function) times out.
If we don't check the file share in read function, then what's left is to add notes in docs and let the read function timeout.
var serviceFarmId string | ||
if metadata.ResourceData.HasChange("service_plan_id") { | ||
serviceFarmId = state.ServicePlanId | ||
existing.SiteProperties.ServerFarmID = utils.String(serviceFarmId) | ||
} | ||
|
||
_, planSKU, err := helpers.ServicePlanInfoForApp(ctx, metadata, *id, serviceFarmId) |
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.
As above, the helper should not be repurposed, and the SKU should be read from the new service plan ID. A new helper for that would be acceptable.
Thanks @jackofallops for the feedbacks. All the code changes in this pr is tend to resolve one issue which is the content share issue under elastic plan. As I mentioned in the description, if user sets The file share check in read function is to ensure the predefined file share exists, otherwise, we throw error instead of waiting for the read function to time out. The service plan check is to determine whether the function is elastic plan. |
@jackofallops @tombuildsstuff , updated th read function, removed the storage file share check. |
azurerm_windows_function_app
, azurerm_linux_function_app
: fix content share not being created automatically issueazurerm_windows_function_app
, azurerm_linux_function_app
- fix content share not being created automatically issue
705f9b0
to
edfa6b5
Compare
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.
Hi @xiaxyi - apologies for the long overdue re-review on this. I hope you don't mind, but I pushed some changes to simplify the updates and remove the need for re-processing some data. Could you look to add a test to cover the case being addressed here, and I think we'll be good to merge once that's in and passing.
Thanks
Thanks @jackofallops for the update, I updated the code and added the test cases for both linux and windows. feel free to let me know if there is anything else needed. |
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.
Hi @xiaxyi
Thanks for adding the tests. I've re-pushed the changes that were lost during the merge main. The ignores in the test suggest this needs some more work, possibly in the functions I've called out in line below if you can take a look?
Thanks!
Thanks @jackofallops for the comments, I applied your change and pushed again, apologize for my mistakes last time. Regarding the acc test import steps, I think we still need to keep the ignore step for those app setting:
As I mentioned in my previous comments, service will try to add the |
Hi @xiaxyi - Apologies, you are correct. These should be ignored on Import as the service does not manage them if absent. I'll message you offline to discuss. |
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.
Thanks @xiaxyi for the updates and patience. This LGTM now 👍
This functionality has been released in v3.48.0 of the Terraform Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you! |
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. |
Fix content share not being created automatically if
WEBSITE_CONTENTOVERVNET
sets to 1.According to the official guidance, "There are scenarios where you must set the WEBSITE_CONTENTSHARE value to a predefined share, such as when you use a secured storage account in a virtual network. In this case, you must set a unique share name for the main function app and the app for each deployment slot."
If the property
WEBSITE_CONTENTOVERVNET
set to 1 inapp_setting
while the users don't specify or specify a non-existed storage file share, they get the error message:fix #17254
fix #14167
fix #19134