diff --git a/docs/wiki/Media/Monitoring/exception_condition.png b/docs/wiki/Media/Monitoring/exception_condition.png new file mode 100644 index 00000000..15a94690 Binary files /dev/null and b/docs/wiki/Media/Monitoring/exception_condition.png differ diff --git a/docs/wiki/Media/Monitoring/logsearch_condition.png b/docs/wiki/Media/Monitoring/logsearch_condition.png new file mode 100644 index 00000000..d302bd29 Binary files /dev/null and b/docs/wiki/Media/Monitoring/logsearch_condition.png differ diff --git a/docs/wiki/Media/Monitoring/transactionsearch.png b/docs/wiki/Media/Monitoring/transactionsearch.png new file mode 100644 index 00000000..188374b7 Binary files /dev/null and b/docs/wiki/Media/Monitoring/transactionsearch.png differ diff --git a/docs/wiki/Monitoring.md b/docs/wiki/Monitoring.md new file mode 100644 index 00000000..7abe275b --- /dev/null +++ b/docs/wiki/Monitoring.md @@ -0,0 +1,70 @@ +# In this Guide + +- [Introduction](#introduction) +- [Troubleshooting AzOps](#troubleshooting-azops) +- [Operationalize monitoring and logging of AzOps](#operationalize-monitoring-and-logging-of-azops) + - [Enable Application Insights Monitoring](#enable-application-insights-monitoring) + - [Create Alert Rules](#create-alert-rules) + +--- + +## Introduction + +The AzOps module generates various logs and metrics to console during execution. The verbosity level is controlled by the numeric value of `Message.Info.Maximum` in `settings.json`. Lower values, like `1`, indicate minimal information, while `9` indicates the highest verbosity ([read more about the different levels](https://psframework.org/documentation/documents/psframework/logging/basics/message-levels.html)). + +> **_Note:_** The default verbosity level is `3`, and increasing it may negatively affect runtime performance. + +## Troubleshooting AzOps + +During normal operations, the default verbosity level is sufficient. However, when troubleshooting, it is advisable to increase the verbosity to at least `5` or `8`. Going up to `9` makes the module very noisy ([read more](https://github.com/azure/azops/wiki/troubleshooting)). + +## Operationalize monitoring and logging of AzOps + +Monitoring and logging takes a leap forward with the capability for AzOps to seamlessly transmit logs to Azure Monitor Application Insights. This integration enhances near real-time visibility, analysis, and optimization, contributing to a more responsive and efficient Azure operational environment. + +![Transaction search](./Media/Monitoring/transactionsearch.png) + +AzOps uses `TrackTrace` to create a "breadcrumb trail" in Application Insights. Warnings and errors are emitted as `TrackException` for diagnosis, and each message generates a `TrackEvent`. Metrics are emitted as `TrackMetric`, such as `AzOpsPush Time` and `AzOpsPull Time` in seconds. + +> Note: This is useful for tracking performance, key metrics, and exceptions over time. It is particularly helpful when running the module with several parallel threads (`Core.ThrottleLimit` > `1`), as console output may not work well in parallel. Emitting information to Azure Monitor Application Insights can overcome this without adjusting `Core.ThrottleLimit`. + +### Enable Application Insights Monitoring + +1. [Create an Application Insights resource](https://learn.microsoft.com/en-us/azure/azure-monitor/app/create-workspace-resource#create-a-workspace-based-resource). +2. Add a secret named `APPLICATIONINSIGHTS_CONNECTIONSTRING` (in GitHub or Azure Pipelines) and enter the connection string for your Application Insights resource ([find your connection string](https://learn.microsoft.com/en-us/azure/azure-monitor/app/sdk-connection-string?tabs=dotnet5#find-your-connection-string)). + + > Note: Create the `APPLICATIONINSIGHTS_CONNECTIONSTRING` secret in the same location where you already have `ARM_TENANT_ID`. If you are using Azure Pipelines, remember to set the variable type to `secret`. + > + > Note: AzOps utilizes the connection string as a secret to authenticate. This requires that local authentication is enabled on the Application Insights resource (due to the high performance impact of Application Insights Microsoft Entra ID-based authentication). + > + > Note: AzOps emits each log event immediately as it happens to ensure messages are not lost. This means each event generates a service call to Application Insights that needs to be authenticated. No batching or schedule is used. + +3. Set the `Core.ApplicationInsights` value in `settings.json` to `true`. AzOps will emit logs to both the console and the designated Azure Monitor Application Insights. + +**_Please Note: For this to work with GitHub in the manner intended (applicable to implementations created prior to AzOps release v2.5.0)_** + +Ensure the `Credentials` section is up-to-date and exists in your [pull.yml, push.yml, redeploy.yml, validate.yml](https://github.com/Azure/AzOps-Accelerator/blob/main/.github/workflows) files. + +```bash +env: + # + # Credentials + # + + APPLICATIONINSIGHTS_CONNECTIONSTRING: ${{ secrets.APPLICATIONINSIGHTS_CONNECTIONSTRING }} +``` + +### Create Alert Rules + +Once monitoring is enabled, implement two essential alert rules using the powerful capabilities of [Azure Monitor alerts](https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-overview). + +1. [Create a metric alert rule](https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-create-metric-alert-rule) with the condition based on the native `exceptions` signal. + - Set a static threshold value of 0 to trigger the alert when the module logs any exception (**Warning, Error, Critical**). + - Recommended alert detail severity: Warning. +![Condition Signal Exceptions](./Media/Monitoring/exception_condition.png) + +2. [Create a log alert rule](https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-create-metric-alert-rule) with the condition based on the native `Custom log search` signal. + - Use the search query `traces | where severityLevel between (3 .. 4)` to trigger the alert for Error or Critical events. + - Enhance the alert by splitting dimensions based on the dimension name `message` and ensure to check `include all future values`. + - Recommended alert detail severity: Critical. +![Condition Signal Exceptions](./Media/Monitoring/logsearch_condition.png) \ No newline at end of file diff --git a/docs/wiki/Settings.md b/docs/wiki/Settings.md index 87b0424f..ed5716ef 100644 --- a/docs/wiki/Settings.md +++ b/docs/wiki/Settings.md @@ -10,37 +10,38 @@ The following configuration values can be modified within the `settings.json` fi | ID | Name | Description | Example | | --- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -| 01 | AutoGeneratedTemplateFolderPath | Generate sub folder for composite resources (/.az) | `"Core.AutoGeneratedTemplateFolderPath": ".az"`
root
└── tenant root group (e42bc18f)
        ├── .az
        │      └── microsoft.management_managementgroups.json
        └── mymanagementgroup (mymanagementgroup)
                └── .az
                        ├── microsoft.authorization_policyassignments.json
                        ├── microsoft.authorization_policydefinitions.json
                        ├── microsoft.authorization_roleassignments.json
                        └── microsoft.management_managementgroups.json -| 02 | AutoInitialize | Run Initialize-AzOpsEnvironment when module is loaded. *Not recommended to change* | `"Core.AutoInitialize": true` | -| 03 | CustomJqTemplatePath | Folder where custom Jq templates are located. | `"Core.CustomJqTemplatePath": ".customtemplates"` | -| 04 | SkipCustomJqTemplate | Do not use custom Jq templates, controls if AzOps looks for custom templates at `CustomJqTemplatePath`. [Read more](https://github.com/azure/azops/wiki/custom-jq-templates) | `"Core.SkipCustomJqTemplate": true` | -| 05 | DefaultDeploymentRegion | Default region for deployments | `"Core.DefaultDeploymentRegion": "northeurope"` | -| 06 | EnrollmentAccountPrincipalName | Default enrollment account for Subscription creation | `"Core.EnrollmentAccountPrincipalName": ""` | -| 07 | ExcludedSubOffer | Exclude specific Subscription offer types from pull | `"Core.ExcludedSubOffer": ["AzurePass_2014-09-01","FreeTrial_2014-09-01","AAD_2015-09-01"]` | -| 08 | ExcludedSubState | Exclude specific states of Subscription from pull | `"Core.ExcludedSubState": ["Disabled","Deleted","Warned","Expired"]` | -| 09 | IgnoreContextCheck | Skip Azure PowerShell context validation. *Not recommended to change* | `"Core.IgnoreContextCheck": false` | -| 10 | IncludeResourcesInResourceGroup | Discover only resources in these resource groups | `"Core.IncludeResourcesInResourceGroup": ["rg1","rg2"]` | -| 11 | IncludeResourceType | Discover only specific resource types [Resource Types](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types) (only targets Resource Group scoped resources) | `"Core.IncludeResourceType": ["Microsoft.Network/privateDnsZones","Microsoft.Network/firewallPolicies"]` | -| 12 | InvalidateCache | Invalidate cached Subscriptions and Management Groups and do a full discovery. *Not recommended to change* | `"Core.InvalidateCache": false` | -| 13 | OfferType | Default offer type for Subscription creation | `"Core.OfferType": "MS-AZR-0017P"` | -| 14 | PartialMgDiscoveryRoot | Generate folder hierachy for specific Management Groups IDs | `"Core.PartialMgDiscoveryRoot": []` | -| 15 | SkipPim | Do not include Privileged Identity Management resources in pull | `"Core.SkipPim": true` | -| 16 | SkipLock | Do not include ResourceLock resources in pull | `"Core.SkipLock": true` | -| 17 | SkipPolicy | Do not include Azure Policy state in pull | `"Core.SkipPolicy": false` | -| 18 | SkipResource | Do not include Resources within Resource Groups | `"Core.SkipResource": false` | -| 18 | SkipChildResource | Do not include Azure child resources | `"Core.SkipChildResource": false` | -| 20 | SkipResourceGroup | Do not include Resource Groups in pull | `"Core.SkipResourceGroup": false` | -| 21 | SkipResourceType | Skip specific [Resource Types](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types) (only targets Resource Group scoped resources) | `"Core.SkipResourceType": ["Microsoft.VSOnline/plans"]` | -| 22 | SkipRole | Do not include Role types in pull | `"Core.SkipRole": false` | -| 23 | State | Folder to store AzOpsState artefact, defaults to `root` | `"Core.State: "/root"` | -| 24 | SubscriptionsToIncludeResourceGroups | Filter which Subscription IDs should include Resource Groups in pull [Logic Updated in v2.0.0](https://github.com/Azure/AzOps/releases/tag/2.0.0) | `"Core.SubscriptionsToIncludeResourceGroups": ["*"]` | -| 25 | TemplateParameterFileSuffix | Default template file suffix. *Not recommended to change* | `"Core.TemplateParameterFileSuffix": ".json"` | -| 26 | AllowMultipleTemplateParameterFiles | Control multiple parameter file behaviour. *Not recommended to change* | `"Core.AllowMultipleTemplateParameterFiles": false` | -| 27 | DeployAllMultipleTemplateParameterFiles | Control base template deployment behaviour with changes and un-changed multiple corresponding parameter files. | `"Core.DeployAllMultipleTemplateParameterFiles": false` | -| 28 | MultipleTemplateParameterFileSuffix | Multiple parameter file suffix identifier. *Example mytemplate.x1.bicepparam* | `"Core.MultipleTemplateParameterFileSuffix": ".x"` | -| 29 | ParallelDeployMultipleTemplateParameterFiles | Control parallel deployment of MultipleTemplateParameterFiles behaviour | `"Core.ParallelDeployMultipleTemplateParameterFiles": false` | -| 30 | ThrottleLimit | Value declaring number of parallel threads. [Read more](https://github.com/azure/azops/wiki/performance-considerations) | `"Core.ThrottleLimit": 5` | -| 31 | WhatifExcludedChangeTypes | Exclude specific change types from WhatIf operations | `"Core.WhatifExcludedChangeTypes": ["NoChange","Ignore"]` | +| 01 | ApplicationInsights | Turn on or off logging to Application Insight | `"Core.ApplicationInsights": true` | +| 02 | AutoGeneratedTemplateFolderPath | Generate sub folder for composite resources (/.az) | `"Core.AutoGeneratedTemplateFolderPath": ".az"`
root
└── tenant root group (e42bc18f)
        ├── .az
        │      └── microsoft.management_managementgroups.json
        └── mymanagementgroup (mymanagementgroup)
                └── .az
                        ├── microsoft.authorization_policyassignments.json
                        ├── microsoft.authorization_policydefinitions.json
                        ├── microsoft.authorization_roleassignments.json
                        └── microsoft.management_managementgroups.json | +| 03 | AutoInitialize | Run Initialize-AzOpsEnvironment when module is loaded. *Not recommended to change* | `"Core.AutoInitialize": true` | +| 04 | CustomJqTemplatePath | Folder where custom Jq templates are located. | `"Core.CustomJqTemplatePath": ".customtemplates"` | +| 05 | SkipCustomJqTemplate | Do not use custom Jq templates, controls if AzOps looks for custom templates at `CustomJqTemplatePath`. [Read more](https://github.com/azure/azops/wiki/custom-jq-templates) | `"Core.SkipCustomJqTemplate": true` | +| 06 | DefaultDeploymentRegion | Default region for deployments | `"Core.DefaultDeploymentRegion": "northeurope"` | +| 07 | EnrollmentAccountPrincipalName | Default enrollment account for Subscription creation | `"Core.EnrollmentAccountPrincipalName": ""` | +| 08 | ExcludedSubOffer | Exclude specific Subscription offer types from pull | `"Core.ExcludedSubOffer": ["AzurePass_2014-09-01","FreeTrial_2014-09-01","AAD_2015-09-01"]` | +| 09 | ExcludedSubState | Exclude specific states of Subscription from pull | `"Core.ExcludedSubState": ["Disabled","Deleted","Warned","Expired"]` | +| 10 | IgnoreContextCheck | Skip Azure PowerShell context validation. *Not recommended to change* | `"Core.IgnoreContextCheck": false` | +| 11 | IncludeResourcesInResourceGroup | Discover only resources in these resource groups | `"Core.IncludeResourcesInResourceGroup": ["rg1","rg2"]` | +| 12 | IncludeResourceType | Discover only specific resource types [Resource Types](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types) (only targets Resource Group scoped resources) | `"Core.IncludeResourceType": ["Microsoft.Network/privateDnsZones","Microsoft.Network/firewallPolicies"]` | +| 13 | InvalidateCache | Invalidate cached Subscriptions and Management Groups and do a full discovery. *Not recommended to change* | `"Core.InvalidateCache": false` | +| 14 | OfferType | Default offer type for Subscription creation | `"Core.OfferType": "MS-AZR-0017P"` | +| 15 | PartialMgDiscoveryRoot | Generate folder hierachy for specific Management Groups IDs | `"Core.PartialMgDiscoveryRoot": []` | +| 16 | SkipPim | Do not include Privileged Identity Management resources in pull | `"Core.SkipPim": true` | +| 17 | SkipLock | Do not include ResourceLock resources in pull | `"Core.SkipLock": true` | +| 18 | SkipPolicy | Do not include Azure Policy state in pull | `"Core.SkipPolicy": false` | +| 19 | SkipResource | Do not include Resources within Resource Groups | `"Core.SkipResource": false` | +| 20 | SkipChildResource | Do not include Azure child resources | `"Core.SkipChildResource": false` | +| 21 | SkipResourceGroup | Do not include Resource Groups in pull | `"Core.SkipResourceGroup": false` | +| 22 | SkipResourceType | Skip specific [Resource Types](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types) (only targets Resource Group scoped resources) | `"Core.SkipResourceType": ["Microsoft.VSOnline/plans"]` | +| 23 | SkipRole | Do not include Role types in pull | `"Core.SkipRole": false` | +| 24 | State | Folder to store AzOpsState artefact, defaults to `root` | `"Core.State: "/root"` | +| 25 | SubscriptionsToIncludeResourceGroups | Filter which Subscription IDs should include Resource Groups in pull [Logic Updated in v2.0.0](https://github.com/Azure/AzOps/releases/tag/2.0.0) | `"Core.SubscriptionsToIncludeResourceGroups": ["*"]` | +| 26 | TemplateParameterFileSuffix | Default template file suffix. *Not recommended to change* | `"Core.TemplateParameterFileSuffix": ".json"` | +| 27 | AllowMultipleTemplateParameterFiles | Control multiple parameter file behaviour. *Not recommended to change* | `"Core.AllowMultipleTemplateParameterFiles": false` | +| 28 | DeployAllMultipleTemplateParameterFiles | Control base template deployment behaviour with changes and un-changed multiple corresponding parameter files. | `"Core.DeployAllMultipleTemplateParameterFiles": false` | +| 29 | MultipleTemplateParameterFileSuffix | Multiple parameter file suffix identifier. *Example mytemplate.x1.bicepparam* | `"Core.MultipleTemplateParameterFileSuffix": ".x"` | +| 30 | ParallelDeployMultipleTemplateParameterFiles | Control parallel deployment of MultipleTemplateParameterFiles behaviour | `"Core.ParallelDeployMultipleTemplateParameterFiles": false` | +| 31 | ThrottleLimit | Value declaring number of parallel threads. [Read more](https://github.com/azure/azops/wiki/performance-considerations) | `"Core.ThrottleLimit": 5` | +| 32 | WhatifExcludedChangeTypes | Exclude specific change types from WhatIf operations | `"Core.WhatifExcludedChangeTypes": ["NoChange","Ignore"]` | ## Workflow / Pipeline Settings diff --git a/docs/wiki/Troubleshooting.md b/docs/wiki/Troubleshooting.md index 62445821..7a5a7856 100644 --- a/docs/wiki/Troubleshooting.md +++ b/docs/wiki/Troubleshooting.md @@ -1,4 +1,4 @@ -### In this guide +# In this guide - [General](#general) - [GitHub Actions](#github-actions) @@ -11,17 +11,14 @@ To enable debug logging for the AzOps module, please add the following configura ```json { - "Version": 1, - "Static": { - "PSFramework.Message.Info.Maximum": 9 + "PSFramework": { + "Message.Info.Maximum": 9 } } ``` ## GitHub Actions -[TODO] - To enable debug logging within GitHub Actions workflows, please visit the [Product Documentation](https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging) --- @@ -46,13 +43,13 @@ Ensure that you're using the $escapedServicePrincipalJson variable string from t Enabling long paths on Windows The Git clone below and AzOps GitHub Action implementation requires that you enable long paths in Windows. To enable this, execute the following command from a terminal with elevated privileges: -``` +```powershell REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f ``` -You will also need to execute the following command line from an elevated terminal: +You will also need to execute the following command-line from an elevated terminal: -``` +```powershell git config --system core.longpaths true ``` diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md index dbc3d845..05f26794 100644 --- a/docs/wiki/_Sidebar.md +++ b/docs/wiki/_Sidebar.md @@ -14,6 +14,7 @@ * [Settings](https://github.com/azure/azops/wiki/settings) * [Custom Jq Templates](https://github.com/azure/azops/wiki/custom-jq-templates) + * [Monitoring](https://github.com/azure/azops/wiki/monitoring) * [Performance Considerations](https://github.com/azure/azops/wiki/performance-considerations) * [Updates](https://github.com/azure/azops/wiki/updates) * [Steps](https://github.com/azure/azops/wiki/steps) diff --git a/src/AzOps.psd1 b/src/AzOps.psd1 index 3d6cc12f..90d033dd 100644 --- a/src/AzOps.psd1 +++ b/src/AzOps.psd1 @@ -3,7 +3,7 @@ # # Generated by: Customer Architecture Team (CAT) # -# Generated on: 12/19/2023 +# Generated on: 1/14/2024 # @{ @@ -52,10 +52,10 @@ PowerShellVersion = '7.2' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @(@{ModuleName = 'PSFramework'; RequiredVersion = '1.10.318'; }, - @{ModuleName = 'Az.Accounts'; RequiredVersion = '2.13.2'; }, + @{ModuleName = 'Az.Accounts'; RequiredVersion = '2.15.0'; }, @{ModuleName = 'Az.Billing'; RequiredVersion = '2.0.3'; }, @{ModuleName = 'Az.ResourceGraph'; RequiredVersion = '0.13.0'; }, - @{ModuleName = 'Az.Resources'; RequiredVersion = '6.12.1'; }) + @{ModuleName = 'Az.Resources'; RequiredVersion = '6.14.0'; }) # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() diff --git a/src/functions/Initialize-AzOpsEnvironment.ps1 b/src/functions/Initialize-AzOpsEnvironment.ps1 index 33cbc621..1600cae6 100644 --- a/src/functions/Initialize-AzOpsEnvironment.ps1 +++ b/src/functions/Initialize-AzOpsEnvironment.ps1 @@ -65,7 +65,7 @@ # Adjust MultipleTemplateParameterFileSuffix if incorrect MultipleTemplateParameterFileSuffix is set and log warning if (-not $(Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix').StartsWith('.')) { $updateMultipleTemplateParameterFileSuffix = ".$(Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix')" - Write-PSFMessage -Level Warning -String 'Initialize-AzOpsEnvironment.MultipleTemplateParameterFileSuffix.Adjustment' -StringValues (Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix'), $updateMultipleTemplateParameterFileSuffix + Write-AzOpsMessage -LogLevel Warning -LogString 'Initialize-AzOpsEnvironment.MultipleTemplateParameterFileSuffix.Adjustment' -LogStringValues (Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix'), $updateMultipleTemplateParameterFileSuffix Set-PSFConfig -Module AzOps -Name Core.MultipleTemplateParameterFileSuffix -Value $updateMultipleTemplateParameterFileSuffix } @@ -73,21 +73,21 @@ [int]$cpuCores = if ($IsWindows) { $env:NUMBER_OF_PROCESSORS } else { Invoke-AzOpsNativeCommand -ScriptBlock { nproc --all } -IgnoreExitcode } $throttleLimit = (Get-PSFConfig -Module AzOps -Name Core.ThrottleLimit).Value if (-not[string]::IsNullOrEmpty($cpuCores) -and $cpuCores -le 2 -and $throttleLimit -gt 5) { - Write-PSFMessage -Level Warning -String 'Initialize-AzOpsEnvironment.ThrottleLimit.Adjustment' -StringValues $throttleLimit, $cpuCores + Write-AzOpsMessage -LogLevel Warning -LogString 'Initialize-AzOpsEnvironment.ThrottleLimit.Adjustment' -LogStringValues $throttleLimit, $cpuCores Set-PSFConfig -Module AzOps -Name Core.ThrottleLimit -Value 5 } # Validate optional custom path for custom jq template if ((Get-PSFConfig -Module AzOps -Name Core.SkipCustomJqTemplate).Value) { - Write-PSFMessage -Level Debug -String 'Initialize-AzOpsEnvironment.SkipCustomJqTemplate.True' + Write-AzOpsMessage -LogLevel Debug -LogString 'Initialize-AzOpsEnvironment.SkipCustomJqTemplate.True' } else { $customJqTemplatePath = (Get-PSFConfig -Module AzOps -Name Core.CustomJqTemplatePath).Value if (Test-Path -Path $customJqTemplatePath) { - Write-PSFMessage -Level Debug -String 'Initialize-AzOpsEnvironment.CustomJqTemplatePath' -StringValues $customJqTemplatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Initialize-AzOpsEnvironment.CustomJqTemplatePath' -LogStringValues $customJqTemplatePath } else { - Write-PSFMessage -Level Warning -String 'Initialize-AzOpsEnvironment.CustomJqTemplatePath.PathNotFound' -StringValues $customJqTemplatePath + Write-AzOpsMessage -LogLevel Warning -LogString 'Initialize-AzOpsEnvironment.CustomJqTemplatePath.PathNotFound' -LogStringValues $customJqTemplatePath Set-PSFConfig -Module AzOps -Name Core.SkipCustomJqTemplate -Value $true } } @@ -96,16 +96,15 @@ process { # If data exists and we don't want to rebuild the data cache, no point in continuing if (-not $InvalidateCache -and $script:AzOpsAzManagementGroup -and $script:AzOpsSubscriptions) { - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.UsingCache' + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.UsingCache' return } #region Initialize & Prepare - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.Processing' + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.Processing' $currentAzContext = Get-AzContext $tenantId = $currentAzContext.Tenant.Id - - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.Initializing' + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.Initializing' if (-not (Test-Path -Path (Get-PSFConfigValue -FullName 'AzOps.Core.State'))) { $null = New-Item -path (Get-PSFConfigValue -FullName 'AzOps.Core.State') -Force -ItemType directory } @@ -120,7 +119,7 @@ $managementGroups = Get-AzManagementGroup -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning -String 'Initialize-AzOpsEnvironment.ManagementGroup.NoManagementGroupAccess' + Write-AzOpsMessage -LogLevel Warning -LogString 'Initialize-AzOpsEnvironment.ManagementGroup.NoManagementGroupAccess' return } @@ -129,7 +128,7 @@ $rootPermissions = Get-AzRoleAssignment -ObjectId $currentPrincipal.id -Scope "/" -ErrorAction SilentlyContinue -WarningAction SilentlyContinue if (-not $rootPermissions) { - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.ManagementGroup.NoRootPermissions' -StringValues $currentAzContext.Account.Id + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.ManagementGroup.NoRootPermissions' -LogStringValues $currentAzContext.Account.Id $PartialMgDiscovery = $true } else { @@ -139,7 +138,7 @@ #region Partial Discovery if ($PartialMgDiscoveryRoot) { - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.ManagementGroup.PartialDiscovery' + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.ManagementGroup.PartialDiscovery' $PartialMgDiscovery = $true $managementGroups = @() foreach ($managementRoot in $PartialMgDiscoveryRoot) { @@ -150,16 +149,16 @@ #endregion Partial Discovery #region Management Group Resolution - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.ManagementGroup.Resolution' -StringValues $managementGroups.Count + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.ManagementGroup.Resolution' -LogStringValues $managementGroups.Count -Metric $managementGroups.Count -MetricName 'ManagementGroup Count' $tempResolved = foreach ($mgmtGroup in $managementGroups) { - Write-PSFMessage -Level Verbose -String 'Initialize-AzOpsEnvironment.ManagementGroup.Expanding' -StringValues $mgmtGroup.Name + Write-AzOpsMessage -LogLevel Verbose -LogString 'Initialize-AzOpsEnvironment.ManagementGroup.Expanding' -LogStringValues $mgmtGroup.Name Get-AzOpsManagementGroup -ManagementGroup $mgmtGroup.Name -PartialDiscovery:$PartialMgDiscovery } $script:AzOpsAzManagementGroup = $tempResolved | Sort-Object -Property Id -Unique #endregion Management Group Resolution #endregion Management Group Processing - - Write-PSFMessage -Level Important -String 'Initialize-AzOpsEnvironment.Processing.Completed' + Write-AzOpsMessage -LogLevel Important -LogString 'Initialize-AzOpsEnvironment.Processing.Completed' + Clear-PSFMessage } } \ No newline at end of file diff --git a/src/functions/Invoke-AzOpsPull.ps1 b/src/functions/Invoke-AzOpsPull.ps1 index f67bbdd5..77f9303c 100644 --- a/src/functions/Invoke-AzOpsPull.ps1 +++ b/src/functions/Invoke-AzOpsPull.ps1 @@ -84,44 +84,44 @@ #region Prepare if (-not $SkipPim) { try { - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPull.Validating.UserRole' + Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.UserRole' $null = Get-AzADUser -First 1 -ErrorAction Stop - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPull.Validating.UserRole.Success' - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPull.Validating.AADP2' + Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.UserRole.Success' + Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.AADP2' $servicePlanName = "AAD_PREMIUM_P2" $subscribedSkus = Invoke-AzRestMethod -Uri https://graph.microsoft.com/v1.0/subscribedSkus -ErrorAction Stop $subscribedSkusValue = $subscribedSkus.Content | ConvertFrom-Json -Depth 100 | Select-Object value if ($servicePlanName -in $subscribedSkusValue.value.servicePlans.servicePlanName) { - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPull.Validating.AADP2.Success' + Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.AADP2.Success' } else { - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsPull.Validating.AADP2.Failed' + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.AADP2.Failed' $SkipPim = $true } } catch { - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsPull.Validating.UserRole.Failed' + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.UserRole.Failed' $SkipPim = $true } } if ($false -eq $SkipChildResource -or $false -eq $SkipResource -and $true -eq $SkipResourceGroup) { - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsPull.Validating.ResourceGroupDiscovery.Failed' -StringValues "`n" + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.ResourceGroupDiscovery.Failed' -LogStringValues "`n" } $resourceTypeDiff = Compare-Object -ReferenceObject $SkipResourceType -DifferenceObject $IncludeResourceType -ExcludeDifferent if ($resourceTypeDiff) { - Write-PSFMessage -Level Warning -Message "SkipResourceType setting conflict found in IncludeResourceType, ignoring $($resourceTypeDiff.InputObject) from IncludeResourceType. To avoid this remove $($resourceTypeDiff.InputObject) from IncludeResourceType or SkipResourceType" + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.SkipResourceType.Failed' -LogStringValues $($resourceTypeDiff.InputObject) $IncludeResourceType = $IncludeResourceType | Where-Object { $_ -notin $resourceTypeDiff.InputObject } } Assert-AzOpsInitialization -Cmdlet $PSCmdlet -StatePath $StatePath $tenantId = (Get-AzContext).Tenant.Id - Write-PSFMessage -Level Important -String 'Invoke-AzOpsPull.Tenant' -StringValues $tenantId - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPull.TemplateParameterFileSuffix' -StringValues (Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix') + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Tenant' -LogStringValues $tenantId + Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.TemplateParameterFileSuffix' -LogStringValues (Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix') - Write-PSFMessage -Level Important -String 'Invoke-AzOpsPull.Initialization.Completed' + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Initialization.Completed' $stopWatch = [System.Diagnostics.Stopwatch]::StartNew() #endregion Initialize & Prepare } @@ -133,7 +133,7 @@ $_.Name -like $("Microsoft.Management_managementGroups-" + $tenantId + $TemplateParameterFileSuffix) } | Select-Object -ExpandProperty FullName -First 1) -notmatch '\((.*)\)' if ($migrationRequired) { - Write-PSFMessage -Level Important -String 'Invoke-AzOpsPull.Migration.Required' + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Migration.Required' } if ($Force -or $migrationRequired) { @@ -158,7 +158,7 @@ # Parameters $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Inherit -Include IncludeResourcesInResourceGroup, IncludeResourceType, SkipPim, SkipLock, SkipPolicy, SkipRole, SkipResourceGroup, SkipChildResource, SkipResource, SkipResourceType, StatePath - Write-PSFMessage -Level Important -String 'Invoke-AzOpsPull.Building.State' -StringValues $StatePath + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Building.State' -LogStringValues $StatePath if ($rootScope -and $script:AzOpsAzManagementGroup) { foreach ($root in $rootScope) { # Create AzOpsState structure recursively @@ -178,7 +178,8 @@ end { $stopWatch.Stop() - Write-PSFMessage -Level Important -String 'Invoke-AzOpsPull.Duration' -StringValues $stopWatch.Elapsed -Data @{ Elapsed = $stopWatch.Elapsed } + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Duration' -LogStringValues $stopWatch.Elapsed -Metric $stopWatch.Elapsed.TotalSeconds -MetricName 'AzOpsPull Time' + Clear-PSFMessage } } \ No newline at end of file diff --git a/src/functions/Invoke-AzOpsPush.ps1 b/src/functions/Invoke-AzOpsPush.ps1 index 5e0e48a3..14a1087d 100644 --- a/src/functions/Invoke-AzOpsPush.ps1 +++ b/src/functions/Invoke-AzOpsPush.ps1 @@ -78,7 +78,7 @@ $fileItem = Get-Item -Path $FilePath if ($fileItem.Extension -notin '.json' , '.bicep', '.bicepparam') { - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsPush.Resolve.NoJson' -StringValues $fileItem.FullName -Tag pwsh -FunctionName 'Invoke-AzOpsPush' -Target $ScopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPush.Resolve.NoJson' -LogStringValues $fileItem.FullName -Target $ScopeObject return } @@ -97,7 +97,7 @@ switch ($fileItem.Name) { { $_.EndsWith('.parameters.json') } { if ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $true -and $fileItem.FullName.Split('.')[-3] -match $(Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix').Replace('.','')) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -StringValues $FilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -LogStringValues $FilePath $templatePath = $fileItem.FullName -replace (".$($fileItem.FullName.Split('.')[-3])"), '' -replace '\.parameters.json', '.json' $bicepTemplatePath = $fileItem.FullName -replace (".$($fileItem.FullName.Split('.')[-3])"), '' -replace '.parameters.json', '.bicep' } @@ -106,7 +106,7 @@ $bicepTemplatePath = $fileItem.FullName -replace '.parameters.json', '.bicep' } if (Test-Path $templatePath) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.FoundTemplate' -StringValues $FilePath, $templatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.FoundTemplate' -LogStringValues $FilePath, $templatePath $result.TemplateFilePath = $templatePath $newScopeObject = New-AzOpsScope -Path $result.TemplateFilePath -StatePath $StatePath -ErrorAction Stop $result.ScopeObject = $newScopeObject @@ -114,7 +114,7 @@ return $result } elseif (Test-Path $bicepTemplatePath) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.FoundBicepTemplate' -StringValues $FilePath, $bicepTemplatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.FoundBicepTemplate' -LogStringValues $FilePath, $bicepTemplatePath $transpiledTemplatePaths = ConvertFrom-AzOpsBicepTemplate -BicepTemplatePath $bicepTemplatePath -SkipParam -ConvertedTemplate $ConvertedTemplate $result.TranspiledTemplateNew = $transpiledTemplatePaths.transpiledTemplateNew $result.TemplateFilePath = $transpiledTemplatePaths.transpiledTemplatePath @@ -126,14 +126,14 @@ } { $_.EndsWith('.bicepparam') } { if ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $true -and $fileItem.FullName.Split('.')[-2] -match $(Get-PSFConfigValue -FullName 'AzOps.Core.MultipleTemplateParameterFileSuffix').Replace('.','')) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -StringValues $FilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -LogStringValues $FilePath $bicepTemplatePath = $fileItem.FullName -replace (".$($fileItem.FullName.Split('.')[-2])"), '' -replace '\.bicepparam', '.bicep' } else { $bicepTemplatePath = $fileItem.FullName -replace '\.bicepparam', '.bicep' } if (Test-Path $bicepTemplatePath) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.FoundBicepTemplate' -StringValues $FilePath, $bicepTemplatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.FoundBicepTemplate' -LogStringValues $FilePath, $bicepTemplatePath $transpiledTemplatePaths = ConvertFrom-AzOpsBicepTemplate -BicepTemplatePath $bicepTemplatePath -BicepParamTemplatePath $fileItem.FullName -ConvertedTemplate $ConvertedTemplate -ConvertedParameter $ConvertedParameter $result.TranspiledTemplateNew = $transpiledTemplatePaths.transpiledTemplateNew $result.TranspiledParametersNew = $transpiledTemplatePaths.transpiledParametersNew @@ -149,9 +149,9 @@ #endregion Directly Associated Template file exists #region Check in the main template file for a match - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Resolve.NotFoundTemplate' -StringValues $FilePath, $templatePath + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Resolve.NotFoundTemplate' -LogStringValues $FilePath, $templatePath $mainTemplateItem = Get-Item $AzOpsMainTemplate - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.FromMainTemplate' -StringValues $mainTemplateItem.FullName + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.FromMainTemplate' -LogStringValues $mainTemplateItem.FullName # Determine Resource Type in Parameter file $templateParameterFileHashtable = Get-Content -Path $fileItem.FullName | ConvertFrom-Json -AsHashtable @@ -173,11 +173,11 @@ # Check if generic template is supporting the resource type for the deployment. if ($effectiveResourceType -and (Get-Content $mainTemplateItem.FullName | ConvertFrom-Json -AsHashtable).variables.apiVersionLookup.Keys -contains $effectiveResourceType) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.MainTemplate.Supported' -StringValues $effectiveResourceType, $mainTemplateItem.FullName + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.MainTemplate.Supported' -LogStringValues $effectiveResourceType, $mainTemplateItem.FullName $result.TemplateFilePath = $mainTemplateItem.FullName return $result } - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsPush.Resolve.MainTemplate.NotSupported' -StringValues $effectiveResourceType, $mainTemplateItem.FullName -Tag pwsh -FunctionName 'Invoke-AzOpsPush' -Target $ScopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPush.Resolve.MainTemplate.NotSupported' -LogStringValues $effectiveResourceType, $mainTemplateItem.FullName -Target $ScopeObject return #endregion Check in the main template file for a match # All Code paths end the command @@ -188,7 +188,7 @@ $result.TemplateFilePath = $fileItem.FullName $parameterPath = Join-Path $fileItem.Directory.FullName -ChildPath ($fileItem.BaseName + '.parameters' + (Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix')) if (Test-Path -Path $parameterPath) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.ParameterFound' -StringValues $FilePath, $parameterPath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.ParameterFound' -LogStringValues $FilePath, $parameterPath $result.TemplateParameterFilePath = $parameterPath } elseif ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $true -and (Get-PSFConfigValue -FullName 'AzOps.Core.DeployAllMultipleTemplateParameterFiles') -eq $true) { @@ -199,7 +199,7 @@ foreach ($paramFile in $paramFileList) { # Process possible parameter files for template equivalent if (($fileItem.FullName.Split('.')[-2] -eq $paramFile.FullName.Split('.')[-3]) -or ($fileItem.FullName.Split('.')[-2] -eq $paramFile.FullName.Split('.')[-4])) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -StringValues $paramFile.FullName + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.MultipleTemplateParameterFile' -LogStringValues $paramFile.FullName $multiResult += Resolve-ArmFileAssociation -ScopeObject $scopeObject -FilePath $paramFile -AzOpsMainTemplate $AzOpsMainTemplate -ConvertedTemplate $ConvertedTemplate -ConvertedParameter $ConvertedParameter } } @@ -208,13 +208,13 @@ return $multiResult } else { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.ParameterNotFound' -StringValues $FilePath, $parameterPath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.ParameterNotFound' -LogStringValues $FilePath, $parameterPath } } } else { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Resolve.ParameterNotFound' -StringValues $FilePath, $parameterPath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.ParameterNotFound' -LogStringValues $FilePath, $parameterPath if ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $true) { # Check for template parameters without defaultValue $defaultValueContent = Get-Content $FilePath @@ -222,7 +222,7 @@ if ($missingDefaultParam.Count -ge 1) { # Skip template deployment when template parameters without defaultValue are found and no parameter file identified $missingString = foreach ($item in $missingDefaultParam.Keys.GetEnumerator()) {"$item,"} - Write-PSFMessage -Level Verbose -String 'Invoke-AzOpsPush.Resolve.NotFoundParamFileDefaultValue' -StringValues $FilePath, ($missingString | Out-String -NoNewline) + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Resolve.NotFoundParamFileDefaultValue' -LogStringValues $FilePath, ($missingString | Out-String -NoNewline) continue } } @@ -252,10 +252,11 @@ # Remove lingering files from previous run $tempPath = [System.IO.Path]::GetTempPath() if ((Test-Path -Path ($tempPath + 'OUTPUT.md')) -or (Test-Path -Path ($tempPath + 'OUTPUT.json'))) { - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFile.Remove' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFile.Remove' Remove-Item -Path ($tempPath + 'OUTPUT.md') -Force -ErrorAction SilentlyContinue Remove-Item -Path ($tempPath + 'OUTPUT.json') -Force -ErrorAction SilentlyContinue } + $stopWatch = [System.Diagnostics.Stopwatch]::StartNew() } process { @@ -264,7 +265,7 @@ #Supported resource types for deletion $DeletionSupportedResourceType = (Get-PSFConfigValue -FullName 'AzOps.Core.DeletionSupportedResourceType') #region Categorize Input - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Deployment.Required' + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Deployment.Required' $deleteSet = @() $addModifySet = foreach ($change in $ChangeSet) { $operation, $filename = ($change -split "`t")[0, -1] @@ -285,20 +286,20 @@ if ($addModifySet -and -not $CustomSortOrder) { $addModifySet = $addModifySet | Sort-Object } if ($addModifySet) { - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Change.AddModify' + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Change.AddModify' foreach ($item in $addModifySet) { - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Change.AddModify.File' -StringValues $item + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Change.AddModify.File'-LogStringValues $item } } if ($DeleteSetContents -and $deleteSet) { - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Change.Delete' + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Change.Delete' # Unique delimiter used to join, split and replace data in DeleteSetContents $delimiter = (New-Guid).Guid # Transform $DeleteSetContents for further processing $DeleteSetContents = $DeleteSetContents -join $delimiter -split "$delimiter-- " -replace $delimiter,"" # Process each $deleteSet $item foreach ($item in $deleteSet) { - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Change.Delete.File' -StringValues $item + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Change.Delete.File' -LogStringValues $item # Processing each $deleteSet, compare it to each $DeleteSetContents foreach ($content in $DeleteSetContents) { if ($content.Contains($item)) { @@ -329,17 +330,17 @@ $newStateDeploymentCmd.Begin($true) foreach ($addition in $addModifySet) { if ($addition -notmatch '/*.subscription.json$') { continue } - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Deploy.Subscription' -StringValues $addition -Target $addition + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Deploy.Subscription' -LogStringValues $addition -Target $addition $newStateDeploymentCmd.Process($addition) } foreach ($addition in $addModifySet) { if ($addition -notmatch '/*.providerfeatures.json$') { continue } - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Deploy.ProviderFeature' -StringValues $addition -Target $addition + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Deploy.ProviderFeature' -LogStringValues $addition -Target $addition $newStateDeploymentCmd.Process($addition) } foreach ($addition in $addModifySet) { if ($addition -notmatch '/*.resourceproviders.json$') { continue } - Write-PSFMessage -Level Important @common -String 'Invoke-AzOpsPush.Deploy.ResourceProvider' -StringValues $addition -Target $addition + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Deploy.ResourceProvider' -LogStringValues $addition -Target $addition $newStateDeploymentCmd.Process($addition) } $newStateDeploymentCmd.End() @@ -375,7 +376,7 @@ $scopeObject = New-AzOpsScope -Path $addition -StatePath $StatePath -ErrorAction Stop } catch { - Write-PSFMessage -Level Debug @common -String 'Invoke-AzOpsPush.Scope.Failed' -StringValues $addition, $StatePath -Target $addition -ErrorRecord $_ + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPush.Scope.Failed' -LogStringValues $addition -Target $addition -ErrorRecord $_ continue } @@ -400,11 +401,11 @@ $templateContent = Get-Content $deletion | ConvertFrom-Json -AsHashtable $schemavalue = '$schema' if ($templateContent.$schemavalue -like "*deploymentParameters.json#" -and (-not($templateContent.parameters.input.value.type -in $DeletionSupportedResourceType))) { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.SkipUnsupportedResource' -StringValues $deletion -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.SkipUnsupportedResource' -LogStringValues $deletion -Target $scopeObject continue } elseif ($templateContent.$schemavalue -like "*deploymentTemplate.json#" -and (-not($templateContent.resources[0].type -in $DeletionSupportedResourceType))) { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.SkipUnsupportedResource' -StringValues $deletion -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.SkipUnsupportedResource' -LogStringValues $deletion -Target $scopeObject continue } @@ -412,7 +413,7 @@ $scopeObject = New-AzOpsScope -Path $deletion -StatePath $StatePath -ErrorAction Stop } catch { - Write-PSFMessage -Level Debug @common -String 'Invoke-AzOpsPush.Scope.Failed' -StringValues $deletion, $StatePath -Target $deletion -ErrorRecord $_ + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPush.Scope.Failed' -LogStringValues $deletion, $StatePath -Target $deletion -ErrorRecord $_ continue } @@ -433,7 +434,7 @@ #If addModifySet exists and no deploymentList has been generated at the same time as the StatePath root has additional directories and AllowMultipleTemplateParameterFiles is default false, exit with terminating error if (($addModifySet -and -not $deploymentList) -and (Get-ChildItem -Path $StatePath -Directory) -and ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $false)) { - Write-PSFMessage -Level Critical @common -String 'Invoke-AzOpsPush.DeploymentList.NotFound' + Write-AzOpsMessage -LogLevel Critical -LogString 'Invoke-AzOpsPush.DeploymentList.NotFound' throw } @@ -445,18 +446,18 @@ #Determine what deployment pattern to adopt serial or parallel if ((Get-PSFConfigValue -FullName 'AzOps.Core.AllowMultipleTemplateParameterFiles') -eq $true -and (Get-PSFConfigValue -FullName 'AzOps.Core.ParallelDeployMultipleTemplateParameterFiles') -eq $true) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.ParallelCondition' + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.ParallelCondition' # Group deployments based on TemplateFilePath $groups = $uniqueDeployment | Group-Object -Property TemplateFilePath | Where-Object { $_.Count -ge '2' -and $_.Name -ne $(Get-Item $AzOpsMainTemplate).FullName } if ($groups) { - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.ParallelGroup' + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.ParallelGroup' $processedTargets = @() # Process each deployment and evaluate serial or parallel deployment pattern foreach ($deployment in $uniqueDeployment) { if ($deployment.TemplateFilePath -in $groups.Name -and $deployment -notin $processedTargets) { # Deployment part of group association for parallel processing, process entire group as parallel deployment $targets = $($groups | Where-Object { $_.Name -eq $deployment.TemplateFilePath }).Group - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.Parallel' -StringValues $deployment.TemplateFilePath, $targets.Count + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.Parallel' -LogStringValues $deployment.TemplateFilePath, $targets.Count # Prepare Input Data for parallel processing $runspaceData = @{ AzOpsPath = "$($script:ModuleRoot)\AzOps.psd1" @@ -486,28 +487,29 @@ $deployment | New-AzOpsDeployment -WhatIf:$runspaceData.WhatIfPreference } } -UseNewRunspace + Clear-PSFMessage # Add targets to processed list to avoid duplicate deployment $processedTargets += $targets } elseif ($deployment -notin $processedTargets) { # Deployment not part of group association for parallel processing, process this as serial deployment - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.Serial' -StringValues $deployment.Count + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.Serial' -LogStringValues $deployment.Count $deploymentResult += $deployment | New-AzOpsDeployment -WhatIf:$WhatIfPreference } else { # Deployment already processed by group association from parallel processing, skip this duplicate deployment - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.Skip' -StringValues $deployment.TemplateFilePath, $deployment.TemplateParameterFilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.Skip' -LogStringValues $deployment.TemplateFilePath, $deployment.TemplateParameterFilePath } } } else { # No deployments with matching TemplateFilePath identified - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.Serial' -StringValues $deployment.Count + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.Serial' -LogStringValues $deployment.Count $deploymentResult += $uniqueDeployment | New-AzOpsDeployment -WhatIf:$WhatIfPreference } } else { # Perform serial deployment only - Write-PSFMessage -Level Verbose @common -String 'Invoke-AzOpsPush.Deployment.Serial' -StringValues $uniqueDeployment.Count + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsPush.Deployment.Serial' -LogStringValues $uniqueDeployment.Count $deploymentResult += $uniqueDeployment | New-AzOpsDeployment -WhatIf:$WhatIfPreference } @@ -524,8 +526,11 @@ $uniqueProperties = 'Scope', 'TemplateFilePath', 'TemplateParameterFilePath' $removalJob = $deletionList | Select-Object $uniqueProperties -Unique | Remove-AzOpsDeployment -WhatIf:$WhatIfPreference if ($removalJob.dependencyMissing -eq $true) { - Write-PSFMessage -Level Critical @common -String 'Invoke-AzOpsPush.Dependency.Missing' + Write-AzOpsMessage -LogLevel Critical -LogString 'Invoke-AzOpsPush.Dependency.Missing' throw } + $stopWatch.Stop() + Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPush.Duration' -LogStringValues $stopWatch.Elapsed -Metric $stopWatch.Elapsed.TotalSeconds -MetricName 'AzOpsPush Time' + Clear-PSFMessage } } \ No newline at end of file diff --git a/src/internal/classes/AzOpsScope.ps1 b/src/internal/classes/AzOpsScope.ps1 index 5155337c..dec3da9f 100644 --- a/src/internal/classes/AzOpsScope.ps1 +++ b/src/internal/classes/AzOpsScope.ps1 @@ -54,22 +54,22 @@ Creates an AzOpsScope based on the specified resource ID #> - Write-PSFMessage -Level Verbose -String 'AzOpsScope.Constructor' -StringValues $scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.Constructor' -LogStringValues $scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.StateRoot = $StateRoot if (Test-Path -Path $scope) { if ((Get-Item $scope -Force).GetType().ToString() -eq 'System.IO.FileInfo') { #Strong confidence based on content - file - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile' -StringValues $scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile' -LogStringValues $scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.InitializeMemberVariablesFromFile($Scope) } else { # Weak confidence based on metadata at scope - directory - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromDirectory' -StringValues $scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromDirectory' -LogStringValues $scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.InitializeMemberVariablesFromDirectory($Scope) } } else { - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariables' -StringValues $scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariables' -LogStringValues $scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.InitializeMemberVariables($Scope) } } @@ -96,7 +96,7 @@ $this.ChildResource = $ChildResource.resourceProvider + '-' + $ChildResource.resourceName # Check and update generated name for invalid filesystem characters and exceeding maximum length $this.ChildResource = $this.ChildResource | Remove-AzOpsInvalidCharacter | Set-AzOpsStringLength - Write-PSFMessage -Level Verbose -String 'AzOpsScope.ChildResource.InitializeMemberVariables' -StringValues $ChildResource.ResourceProvider, $ChildResource.ResourceName, $scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.ChildResource.InitializeMemberVariables' -LogStringValues $ChildResource.ResourceProvider, $ChildResource.ResourceName, $scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.InitializeMemberVariables($Scope) } @@ -110,30 +110,30 @@ if ($Path.FullName -eq (Get-Item $this.StateRoot -Force).FullName) { # Root tenant path - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromDirectory.RootTenant' -StringValues $Path -FunctionName InitializeMemberVariablesFromDirectory -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromDirectory.RootTenant' -LogStringValues $Path -FunctionName "InitializeMemberVariablesFromDirectory" -ModuleName "AzOps" $this.InitializeMemberVariables("/") return } # Always look into AutoGeneratedTemplateFolderPath folder regardless of path specified if ($Path.FullName -notlike "*$(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath')") { $Path = Join-Path $Path -ChildPath "$(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath')".ToLower() - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromDirectory.AutoGeneratedFolderPath' -StringValues $Path -FunctionName InitializeMemberVariablesFromDirectory -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromDirectory.AutoGeneratedFolderPath' -LogStringValues $Path -FunctionName "InitializeMemberVariablesFromDirectory" -ModuleName "AzOps" } if ($managementGroupScopeFile = (Get-ChildItem -Force -Path $Path -File | Where-Object Name -like $managementGroupFileName)) { [string] $managementGroupID = $managementGroupScopeFile.Name.Replace('microsoft.management_managementgroups-', '').Replace('.parameters', '').Replace($(Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix'), '') - Write-PSFMessage -Level Verbose -String 'AzOpsScope.Input.FromFileName.ManagementGroup' -StringValues $managementGroupID -FunctionName InitializeMemberVariablesFromDirectory -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.Input.FromFileName.ManagementGroup' -LogStringValues $managementGroupID -FunctionName "InitializeMemberVariablesFromDirectory" -ModuleName "AzOps" $this.InitializeMemberVariables("/providers/Microsoft.Management/managementGroups/$managementGroupID") } elseif ($subscriptionScopeFileName = (Get-ChildItem -Force -Path $Path -File | Where-Object Name -like $subscriptionFileName)) { [string] $subscriptionID = $subscriptionScopeFileName.Name.Replace('microsoft.subscription_subscriptions-', '').Replace('.parameters', '').Replace($(Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix'), '') - Write-PSFMessage -Level Verbose -String 'AzOpsScope.Input.FromFileName.Subscription' -StringValues $subscriptionID -FunctionName InitializeMemberVariablesFromDirectory -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.Input.FromFileName.Subscription' -LogStringValues $subscriptionID -FunctionName "InitializeMemberVariablesFromDirectory" -ModuleName "AzOps" $this.InitializeMemberVariables("/subscriptions/$subscriptionID") } elseif ((Get-ChildItem -Force -Path $Path -File | Where-Object Name -like $resourceGroupFileName) -or ((Get-ChildItem -Force -Path $Path.Parent -File | Where-Object Name -like $subscriptionFileName)) ) { - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromDirectory.ParentSubscription' -StringValues $Path.Parent -FunctionName InitializeMemberVariablesFromDirectory -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromDirectory.ParentSubscription' -LogStringValues $Path.Parent -FunctionName "InitializeMemberVariablesFromDirectory" -ModuleName "AzOps" if ($(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath') -match $Path.Name) { $parent = New-AzOpsScope -Path ($Path.Parent.Parent) @@ -148,7 +148,7 @@ } else { #Error - Write-PSFMessage -Level Warning -Tag error -String 'AzOpsScope.Input.BadData.UnknownType' -StringValues $Path -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Warning -LogString 'AzOpsScope.Input.BadData.UnknownType' -LogStringValues $Path -FunctionName "AzOpsScope" -ModuleName "AzOps" throw "Invalid File Structure! Cannot find Management Group / Subscription / Resource Group files in $Path!" } } @@ -159,7 +159,7 @@ if ($Path.Extension -ne '.json') { # Try to determine based on directory - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.NotJson' -StringValues $Path -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.NotJson' -LogStringValues $Path -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $this.InitializeMemberVariablesFromDirectory($Path.Directory) return } @@ -176,26 +176,26 @@ switch ($resourcePath) { { $_.parameters.input.value.Keys -contains "ResourceId" } { # Parameter Files - resource from parameters file - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceId' -StringValues $($resourcePath.parameters.input.value.ResourceId) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceId' -LogStringValues $($resourcePath.parameters.input.value.ResourceId) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $this.InitializeMemberVariables($resourcePath.parameters.input.value.ResourceId) break } { $_.parameters.input.value.Keys -contains "Id" } { # Parameter Files - ManagementGroup and Subscription - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.Id' -StringValues $($resourcePath.parameters.input.value.Id) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.Id' -LogStringValues $($resourcePath.parameters.input.value.Id) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $this.InitializeMemberVariables($resourcePath.parameters.input.value.Id) break } { $_.parameters.input.value.Keys -ccontains "Type" } { # Parameter Files - Determine Resource Type and Name (Management group) # Management group resource id do contain '/provider' - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.Type' -StringValues ("$($resourcePath.parameters.input.value.Type)/$($resourcePath.parameters.input.value.Name)") -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.Type' -LogStringValues ("$($resourcePath.parameters.input.value.Type)/$($resourcePath.parameters.input.value.Name)") -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $this.InitializeMemberVariables("$($resourcePath.parameters.input.value.Type)/$($resourcePath.parameters.input.value.Name)") break } { $_.parameters.input.value.Keys -contains "ResourceType" } { # Parameter Files - Determine Resource Type and Name (Any ResourceType except management group) - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceType' -StringValues ($resourcePath.parameters.input.value.ResourceType) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceType' -LogStringValues ($resourcePath.parameters.input.value.ResourceType) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $currentScope = New-AzOpsScope -Path ($Path.Directory) # Creating Resource Id based on current scope, resource Type and Name of the resource @@ -204,7 +204,7 @@ } { $_.parameters.input.value.Keys -ccontains "type" } { # Parameter Files - Determine resource type and name (Any ResourceType except management group) - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceType' -StringValues ($resourcePath.parameters.input.value.type) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.ResourceType' -LogStringValues ($resourcePath.parameters.input.value.type) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $currentScope = New-AzOpsScope -Path ($Path.Directory) # Creating Resource Id based on current scope, resource type and name of the resource @@ -214,7 +214,7 @@ { $_.resources -and $_.resources[0].type -eq 'Microsoft.Management/managementGroups' } { # Template - Management Group - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.managementgroups' -StringValues ($_.resources[0].name) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.managementgroups' -LogStringValues ($_.resources[0].name) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $currentScope = New-AzOpsScope -Path ($Path.Directory) $this.InitializeMemberVariables("$($currentScope.scope)") break @@ -222,14 +222,14 @@ { $_.resources -and $_.resources[0].type -eq 'Microsoft.Management/managementGroups/subscriptions' } { # Template - Subscription - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.subscriptions' -StringValues ($_.resources[0].name) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.subscriptions' -LogStringValues ($_.resources[0].name) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" $currentScope = New-AzOpsScope -Path ($Path.Directory.Parent) $this.InitializeMemberVariables("$($currentScope.scope)") break } { $_.resources -and $_.resources[0].type -eq 'Microsoft.Resources/resourceGroups' } { - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.resourceGroups' -StringValues ($_.resources[0].name) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.resourceGroups' -LogStringValues ($_.resources[0].name) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" if ($(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath') -match $Path.Directory.Name) { $currentScope = New-AzOpsScope -Path ($Path.Directory.Parent) @@ -243,7 +243,7 @@ } { $_.resources } { # Template - 1st resource - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromFile.resource' -StringValues ($_.resources[0].type), ($_.resources[0].name) -FunctionName InitializeMemberVariablesFromFile -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromFile.resource' -LogStringValues ($_.resources[0].type), ($_.resources[0].name) -FunctionName "InitializeMemberVariablesFromFile" -ModuleName "AzOps" if ($(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath') -match $Path.Directory.Name) { $currentScope = New-AzOpsScope -Path ($Path.Directory.Parent) @@ -258,10 +258,9 @@ Default { # Only show warning about parameter file if parameter file doesn't have deploymentParameters schema defined if ($resourcePath.'$schema' -notmatch 'deploymentParameters.json') { - Write-PSFMessage -Level Warning -String 'AzOpsScope.Input.BadData.TemplateParameterFile' -StringValues $Path -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Warning -LogString 'AzOpsScope.Input.BadData.TemplateParameterFile' -LogStringValues $Path -FunctionName "AzOpsScope" -ModuleName "AzOps" } - - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariablesFromDirectory' -StringValues $Path -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariablesFromDirectory' -LogStringValues $Path -FunctionName "AzOpsScope" -ModuleName "AzOps" $this.InitializeMemberVariablesFromDirectory($Path.Directory) } } @@ -270,7 +269,7 @@ #endregion Constructors hidden [void] InitializeMemberVariables([string]$Scope) { - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariables.Start' -StringValues ($scope) -FunctionName InitializeMemberVariables -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariables.Start' -LogStringValues ($scope) -FunctionName "InitializeMemberVariables" -ModuleName "AzOps" $this.Scope = $Scope if ($this.IsResource()) { @@ -337,7 +336,7 @@ $this.Name = "/" $this.StatePath = $this.StateRoot.ToLower() } - Write-PSFMessage -Level Verbose -String 'AzOpsScope.InitializeMemberVariables.End' -StringValues ($scope) -FunctionName InitializeMemberVariables -ModuleName AzOps + Write-AzOpsMessage -LogLevel InternalComment -LogString 'AzOpsScope.InitializeMemberVariables.End' -LogStringValues ($scope) -FunctionName "InitializeMemberVariables" -ModuleName "AzOps" } #endregion Initializers @@ -411,7 +410,7 @@ } if (-not $private:mgmtHit) { $mgId = $this.Scope -split $this.regex_managementgroupExtract -split '/' | Where-Object { $_ } | Select-Object -First 1 - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetManagementGroup.NotFound' -StringValues $mgId -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetManagementGroup.NotFound' -LogStringValues $mgId -FunctionName "AzOpsScope" -ModuleName "AzOps" return $mgId } } @@ -442,7 +441,7 @@ } } else { - Write-PSFMessage -Level Warning -Tag error -String 'AzOpsScope.GetAzOpsManagementGroupPath.NotFound' -StringValues $managementgroupName -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Warning -LogString 'AzOpsScope.GetAzOpsManagementGroupPath.NotFound' -LogStringValues $managementgroupName -FunctionName "AzOpsScope" -ModuleName "AzOps" $assumeNewResource = "azopsscope-assume-new-resource_$managementgroupName" return $assumeNewResource.ToLower() } @@ -454,11 +453,11 @@ if ($mgId) { $mgName = ($script:AzOpsAzManagementGroup | Where-Object Name -eq $mgId).Name if ($mgName) { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetManagementGroupName.Found.Azure' -StringValues $mgName -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetManagementGroupName.Found.Azure' -LogStringValues $mgName -FunctionName "AzOpsScope" -ModuleName "AzOps" return $mgName } else { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetManagementGroupName.NotFound' -StringValues $mgId -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetManagementGroupName.NotFound' -LogStringValues $mgId -FunctionName "AzOpsScope" -ModuleName "AzOps" return $mgId } } @@ -492,11 +491,11 @@ $subId = $this.Scope -split $this.regex_subscriptionExtract -split '/' | Where-Object { $_ } | Select-Object -First 1 $sub = $script:AzOpsSubscriptions | Where-Object subscriptionId -eq $subId if ($sub) { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetSubscription.Found' -StringValues $sub.Id -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetSubscription.Found' -LogStringValues $sub.Id -FunctionName "AzOpsScope" -ModuleName "AzOps" return $sub.subscriptionId } else { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetSubscription.NotFound' -StringValues $subId -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetSubscription.NotFound' -LogStringValues $subId -FunctionName "AzOpsScope" -ModuleName "AzOps" return $subId } } @@ -507,11 +506,11 @@ $subId = $this.Scope -split $this.regex_subscriptionExtract -split '/' | Where-Object { $_ } | Select-Object -First 1 $sub = $script:AzOpsSubscriptions | Where-Object subscriptionId -eq $subId if ($sub) { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetSubscriptionDisplayName.Found' -StringValues $sub.displayName -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetSubscriptionDisplayName.Found' -LogStringValues $sub.displayName -FunctionName "AzOpsScope" -ModuleName "AzOps" return $sub.displayName } else { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetSubscriptionDisplayName.NotFound' -StringValues $subId -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetSubscriptionDisplayName.NotFound' -LogStringValues $subId -FunctionName "AzOpsScope" -ModuleName "AzOps" return $subId } } @@ -537,7 +536,7 @@ } [string] GetAzOpsResourcePath() { - Write-PSFMessage -Level Debug -String 'AzOpsScope.GetAzOpsResourcePath.Retrieving' -StringValues $this.Scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Debug -LogString 'AzOpsScope.GetAzOpsResourcePath.Retrieving' -LogStringValues $this.Scope -FunctionName "AzOpsScope" -ModuleName "AzOps" $childpath = $this.Name | Remove-AzOpsInvalidCharacter if ($this.Scope -match $this.regex_resourceGroupResource) { $rgpath = $this.GetAzOpsResourceGroupPath() @@ -551,7 +550,7 @@ $mgmtPath = $this.GetAzOpsManagementGroupPath($this.ManagementGroup) return (Join-Path (Join-Path $mgmtPath -ChildPath "$(Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath')".ToLower()) -ChildPath ($this.ResourceProvider + "_" + $this.Resource + "-" + $childpath).ToLower()) } - Write-PSFMessage -Level Warning -Tag error -String 'AzOpsScope.GetAzOpsResourcePath.NotFound' -StringValues $this.Scope -FunctionName AzOpsScope -ModuleName AzOps + Write-AzOpsMessage -LogLevel Warning -LogString 'AzOpsScope.GetAzOpsResourcePath.NotFound' -LogStringValues $this.Scope -FunctionName "AzOpsScope" -ModuleName "AzOps" throw "Unable to determine Resource Scope for: $($this.Scope)" } #endregion Data Accessors diff --git a/src/internal/configurations/Core.ps1 b/src/internal/configurations/Core.ps1 index 95bb1284..12cb50a1 100644 --- a/src/internal/configurations/Core.ps1 +++ b/src/internal/configurations/Core.ps1 @@ -1,4 +1,5 @@ -Set-PSFConfig -Module AzOps -Name Core.AutoGeneratedTemplateFolderPath -Value "." -Initialize -Validation string -Description 'Auto-Generated Template Folder Path i.e. ./Az' +Set-PSFConfig -Module AzOps -Name Core.ApplicationInsights -Value $false -Initialize -Validation bool -Description 'Global flag to turn on or off logging to Application Insight' +Set-PSFConfig -Module AzOps -Name Core.AutoGeneratedTemplateFolderPath -Value "." -Initialize -Validation string -Description 'Auto-Generated Template Folder Path i.e. ./Az' Set-PSFConfig -Module AzOps -Name Core.AutoInitialize -Value $false -Initialize -Validation bool -Description '-' Set-PSFConfig -Module AzOps -Name Core.DeletionSupportedResourceType -Value @('Microsoft.Authorization/locks', 'locks', 'Microsoft.Authorization/policyAssignments', 'policyAssignments', 'Microsoft.Authorization/policyDefinitions', 'policyDefinitions', 'Microsoft.Authorization/policyExemptions', 'policyExemptions', 'Microsoft.Authorization/policySetDefinitions', 'policySetDefinitions', 'Microsoft.Authorization/roleAssignments', 'roleAssignments') -Initialize -Validation stringarray -Description 'Global flag declaring resource types supported for deletion by AzOps.' Set-PSFConfig -Module AzOps -Name Core.DefaultDeploymentRegion -Value northeurope -Initialize -Validation string -Description 'Default deployment region for state deployments (ARM region, not region where a resource is deployed)' diff --git a/src/internal/functions/Assert-AzOpsBicepDependency.ps1 b/src/internal/functions/Assert-AzOpsBicepDependency.ps1 index 5d21a681..d24752ef 100644 --- a/src/internal/functions/Assert-AzOpsBicepDependency.ps1 +++ b/src/internal/functions/Assert-AzOpsBicepDependency.ps1 @@ -18,18 +18,18 @@ ) process { - Write-PSFMessage -Level InternalComment -String 'Assert-AzOpsBicepDependency.Validating' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Assert-AzOpsBicepDependency.Validating' $result = (Invoke-AzOpsNativeCommand -ScriptBlock { bicep --version } -IgnoreExitcode) $installed = $result -as [bool] if ($installed) { - Write-PSFMessage -Level InternalComment -String 'Assert-AzOpsBicepDependency.Success' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Assert-AzOpsBicepDependency.Success' } else { $exception = [System.InvalidOperationException]::new('Unable to locate bicep installation') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "ConfigurationError", 'InvalidOperation', $null) - Write-PSFMessage -Level Warning -String 'Assert-AzOpsBicepDependency.NotFound' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsBicepDependency.NotFound' $Cmdlet.ThrowTerminatingError($errorRecord) } diff --git a/src/internal/functions/Assert-AzOpsInitialization.ps1 b/src/internal/functions/Assert-AzOpsInitialization.ps1 index 8e2deb02..21f763bf 100644 --- a/src/internal/functions/Assert-AzOpsInitialization.ps1 +++ b/src/internal/functions/Assert-AzOpsInitialization.ps1 @@ -33,13 +33,13 @@ process { $stateGood = $StatePath -and $StatePath -notmatch $invalidPathPattern if (-not $stateGood) { - Write-PSFMessage -Level Warning -String 'Assert-AzOpsInitialization.StateError' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsInitialization.StateError' $exception = [System.InvalidOperationException]::new($strings.'Assert-AzOpsInitialization.StateError') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "BadData", 'InvalidData', $null) } $cacheBuilt = $script:AzOpsSubscriptions -or $script:AzOpsAzManagementGroup if (-not $cacheBuilt) { - Write-PSFMessage -Level Warning -String 'Assert-AzOpsInitialization.NoCache' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsInitialization.NoCache' $exception = [System.InvalidOperationException]::new($strings.'Assert-AzOpsInitialization.NoCache') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "NoCache", 'InvalidData', $null) } diff --git a/src/internal/functions/Assert-AzOpsJqDependency.ps1 b/src/internal/functions/Assert-AzOpsJqDependency.ps1 index 62635033..643ba7cc 100644 --- a/src/internal/functions/Assert-AzOpsJqDependency.ps1 +++ b/src/internal/functions/Assert-AzOpsJqDependency.ps1 @@ -18,7 +18,7 @@ ) process { - Write-PSFMessage -Level InternalComment -String 'Assert-AzOpsJqDependency.Validating' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Assert-AzOpsJqDependency.Validating' $result = (Invoke-AzOpsNativeCommand -ScriptBlock { jq --version } -IgnoreExitcode) $installed = $result -as [bool] @@ -26,20 +26,20 @@ if ($installed) { [double]$version = ($result).Split("-")[1] if ($version -ge 1.6) { - Write-PSFMessage -Level InternalComment -String 'Assert-AzOpsJqDependency.Success' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Assert-AzOpsJqDependency.Success' return } else { $exception = [System.InvalidOperationException]::new('Unsupported version of jq installed. Please update to a minimum jq version of 1.6') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "ConfigurationError", 'InvalidOperation', $null) - Write-PSFMessage -Level Warning -String 'Assert-AzOpsJqDependency.Failed' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsJqDependency.Failed' $Cmdlet.ThrowTerminatingError($errorRecord) } } $exception = [System.InvalidOperationException]::new('Unable to locate jq installation') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "ConfigurationError", 'InvalidOperation', $null) - Write-PSFMessage -Level Warning -String 'Assert-AzOpsJqDependency.Failed' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsJqDependency.Failed' $Cmdlet.ThrowTerminatingError($errorRecord) } diff --git a/src/internal/functions/Assert-AzOpsWindowsLongPath.ps1 b/src/internal/functions/Assert-AzOpsWindowsLongPath.ps1 index efb1d782..6ec61474 100644 --- a/src/internal/functions/Assert-AzOpsWindowsLongPath.ps1 +++ b/src/internal/functions/Assert-AzOpsWindowsLongPath.ps1 @@ -22,8 +22,7 @@ if (-not $IsWindows) { return } - - Write-PSFMessage -Level InternalComment -String 'Assert-AzOpsWindowsLongPath.Validating' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Assert-AzOpsWindowsLongPath.Validating' $hasRegKey = 1 -eq (Get-ItemPropertyValue -Path HKLM:SYSTEM\CurrentControlSet\Control\FileSystem -Name LongPathsEnabled) $hasGitConfig = (Invoke-AzOpsNativeCommand -ScriptBlock { git config --system -l } -IgnoreExitcode | Select-String 'core.longpaths=true') -as [bool] if (-not $hasGitConfig) { @@ -35,15 +34,15 @@ return } if (-not $hasRegKey) { - Write-PSFMessage -Level Warning -String 'Assert-AzOpsWindowsLongPath.No.Registry' + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsWindowsLongPath.No.Registry' } if (-not $hasGitConfig) { - Write-PSFMessage -Level Warning -String 'Assert-AzOpsWindowsLongPath.No.GitCfg' + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsWindowsLongPath.No.GitCfg' } $exception = [System.InvalidOperationException]::new('Windows not configured for long paths. Please follow instructions for "Enabling long paths on Windows" on https://github.com/azure/azops/wiki/troubleshooting#windows.') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "ConfigurationError", 'InvalidOperation', $null) - Write-PSFMessage -Level Warning -String 'Assert-AzOpsWindowsLongPath.Failed' -Tag error + Write-AzOpsMessage -LogLevel Warning -LogString 'Assert-AzOpsWindowsLongPath.Failed' $Cmdlet.ThrowTerminatingError($errorRecord) } diff --git a/src/internal/functions/ConvertFrom-AzOpsBicepTemplate.ps1 b/src/internal/functions/ConvertFrom-AzOpsBicepTemplate.ps1 index 4aa0a2d3..72fad8cc 100644 --- a/src/internal/functions/ConvertFrom-AzOpsBicepTemplate.ps1 +++ b/src/internal/functions/ConvertFrom-AzOpsBicepTemplate.ps1 @@ -47,13 +47,13 @@ $transpiledTemplatePath = [IO.Path]::GetFullPath("$($BicepTemplatePath -replace '\.bicep', '.json')") if ($transpiledTemplatePath -notin $ConvertedTemplate) { # Convert bicep template - Write-PSFMessage -Level Verbose -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepTemplate' -StringValues $BicepTemplatePath, $transpiledTemplatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepTemplate' -LogStringValues $BicepTemplatePath, $transpiledTemplatePath Invoke-AzOpsNativeCommand -ScriptBlock { bicep build $bicepTemplatePath --outfile $transpiledTemplatePath } $transpiledTemplateNew = $true # Check if bicep build created (ARM) template if (-not (Test-Path $transpiledTemplatePath)) { # If bicep build did not produce file exit with error - Write-PSFMessage -Level Error -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepTemplate.Error' -StringValues $BicepTemplatePath + Write-AzOpsMessage -LogLevel Error -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepTemplate.Error' -LogStringValues $BicepTemplatePath throw } } @@ -61,30 +61,30 @@ if (-not $BicepParamTemplatePath) { # Check if bicep template has associated bicepparam file $bicepParametersPath = $BicepTemplatePath -replace '\.bicep', '.bicepparam' - Write-PSFMessage -Level Verbose -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam' -StringValues $BicepTemplatePath, $bicepParametersPath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam' -LogStringValues $BicepTemplatePath, $bicepParametersPath } elseif ($BicepParamTemplatePath) { # BicepParamTemplatePath path provided as input $bicepParametersPath = $BicepParamTemplatePath - Write-PSFMessage -Level Verbose -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam' -StringValues $BicepTemplatePath, $bicepParametersPath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam' -LogStringValues $BicepTemplatePath, $bicepParametersPath } if ($bicepParametersPath -and (Test-Path $bicepParametersPath)) { $transpiledParametersPath = [IO.Path]::GetFullPath("$($bicepParametersPath -replace '\.bicepparam', '.parameters.json')") if ($transpiledParametersPath -notin $ConvertedParameter) { # Convert bicepparam to ARM parameter file - Write-PSFMessage -Level Verbose -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepParam' -StringValues $bicepParametersPath, $transpiledParametersPath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepParam' -LogStringValues $bicepParametersPath, $transpiledParametersPath Invoke-AzOpsNativeCommand -ScriptBlock { bicep build-params $bicepParametersPath --outfile $transpiledParametersPath } $transpiledParametersNew = $true # Check if bicep build-params created (ARM) parameters if (-not (Test-Path $transpiledParametersPath)) { # If bicep build-params did not produce file exit with error - Write-PSFMessage -Level Error -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepParam.Error' -StringValues $bicepParametersPath + Write-AzOpsMessage -LogLevel Error -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.ConvertBicepParam.Error' -LogStringValues $bicepParametersPath throw } } } else { - Write-PSFMessage -Level Verbose -String 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam.NotFound' -StringValues $BicepTemplatePath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertFrom-AzOpsBicepTemplate.Resolve.BicepParam.NotFound' -LogStringValues $BicepTemplatePath } } # Return transpiled (ARM) template paths diff --git a/src/internal/functions/ConvertTo-AzOpsState.ps1 b/src/internal/functions/ConvertTo-AzOpsState.ps1 index dbb69572..a519c570 100644 --- a/src/internal/functions/ConvertTo-AzOpsState.ps1 +++ b/src/internal/functions/ConvertTo-AzOpsState.ps1 @@ -60,24 +60,27 @@ ) begin { - Write-PSFMessage -Level Debug -String 'ConvertTo-AzOpsState.Starting' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'ConvertTo-AzOpsState.Starting' } process { - Write-PSFMessage -Level Debug -String 'ConvertTo-AzOpsState.Processing' -StringValues $Resource.Id - if ($ChildResource) { + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Processing' -LogStringValues $ChildResource.resourceName + $objectFilePath = (New-AzOpsScope -scope $ChildResource.parentResourceId -ChildResource $ChildResource -StatePath $Statepath).statepath $jqJsonTemplate = Get-AzOpsTemplateFile -File "templateChildResource.jq" - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Subscription.ChildResource.Jq.Template' -StringValues $jqJsonTemplate + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Subscription.ChildResource.Jq.Template' -LogStringValues $jqJsonTemplate $object = ($Resource | ConvertTo-Json -Depth 100 -EnumsAsStrings | jq -r '--sort-keys' | jq -r -f $jqJsonTemplate | ConvertFrom-Json) - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Subscription.ChildResource.Exporting' -StringValues $objectFilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Subscription.ChildResource.Exporting' -LogStringValues $objectFilePath ConvertTo-Json -InputObject $object -Depth 100 -EnumsAsStrings | Set-Content -Path $objectFilePath -Encoding UTF8 -Force return } + else { + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Processing' -LogStringValues $Resource.id + } if (-not $ExportPath) { if ($Resource.Id) { @@ -93,7 +96,7 @@ $objectFilePath = (New-AzOpsScope -scope $Resource.ResourceId -StatePath $StatePath).statepath } else { - Write-PSFMessage -Level Error -String "ConvertTo-AzOpsState.NoExportPath" -StringValues $Resource.GetType() + Write-AzOpsMessage -LogLevel Error -LogString 'ConvertTo-AzOpsState.NoExportPath' -LogStringValues $Resource.GetType() } } else { @@ -101,28 +104,28 @@ } # Create folder structure if it doesn't exist if (-not (Test-Path -Path $objectFilePath)) { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.File.Create' -StringValues $objectFilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.File.Create' -LogStringValues $objectFilePath $null = New-Item -Path $objectFilePath -ItemType "file" -Force } else { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.File.UseExisting' -StringValues $objectFilePath + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.File.UseExisting' -LogStringValues $objectFilePath } # If export file path ends with parameter $generateTemplateParameter = $objectFilePath.EndsWith('.parameters.json') ? $true : $false - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplateParameter' -StringValues "$generateTemplateParameter" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplateParameter' -LogStringValues "$generateTemplateParameter" $resourceType = $null switch ($Resource) { { $_.ResourceType } { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.ResourceType' -StringValues "$($Resource.ResourceType)" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.ResourceType' -LogStringValues "$($Resource.ResourceType)" $resourceType = $_.ResourceType break } # Management Groups { $_ -is [Microsoft.Azure.Commands.Resources.Models.ManagementGroups.PSManagementGroup] -or $_ -is [Microsoft.Azure.Commands.Resources.Models.ManagementGroups.PSManagementGroupChildInfo] } { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -StringValues "$($_.GetType())" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -LogStringValues "$($_.GetType())" if ($_.Type -eq "/subscriptions") { $resourceType = 'Microsoft.Management/managementGroups/subscriptions' break @@ -134,7 +137,7 @@ } # Subscriptions { $_ -is [Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription] } { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -StringValues "$($_.GetType())" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -LogStringValues "$($_.GetType())" $resourceType = 'Microsoft.Subscription/subscriptions' if (-not $Resource.Type) { $Resource | Add-Member -NotePropertyName Type -NotePropertyValue $resourceType @@ -143,13 +146,13 @@ } # Resource Groups { $_ -is [Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroup] } { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -StringValues "$($_.GetType())" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -LogStringValues "$($_.GetType())" $resourceType = 'Microsoft.Resources/resourceGroups' break } # Resources - Controlled group for raw objects { $_ -is [Microsoft.Azure.Commands.Profile.Models.PSAzureTenant] } { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -StringValues "$($_.GetType())" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.PSObject' -LogStringValues "$($_.GetType())" break } { $_.type } { @@ -159,37 +162,37 @@ else { $resourceType = $_.type } - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.ObjectType.Resolved.ResourceType' -StringValues $resourceType -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.ResourceType' -LogStringValues $resourceType break } Default { - Write-PSFMessage -Level Warning -String 'ConvertTo-AzOpsState.ObjectType.Resolved.Generic' -StringValues "$($_.GetType())" -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Warning -LogString 'ConvertTo-AzOpsState.ObjectType.Resolved.Generic' -LogStringValues "$($_.GetType())" break } } if ($resourceType) { $providerNamespace = ($resourceType -split '/' | Select-Object -First 1) - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ProviderNamespace' -StringValues $providerNamespace -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ProviderNamespace' -LogStringValues $providerNamespace if (($resourceType -split '/').Count -eq 2) { $resourceTypeName = (($resourceType -split '/', 2) | Select-Object -Last 1) - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ResourceTypeName' -StringValues $resourceTypeName -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ResourceTypeName' -LogStringValues $resourceTypeName $resourceApiTypeName = (($resourceType -split '/', 2) | Select-Object -Last 1) - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ResourceApiTypeName' -StringValues $resourceApiTypeName -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ResourceApiTypeName' -LogStringValues $resourceApiTypeName } if (($resourceType -split '/').Count -eq 3) { $resourceTypeName = ((($resourceType -split '/', 3) | Select-Object -Last 2) -join '/') - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ResourceTypeName' -StringValues $resourceTypeName -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ResourceTypeName' -LogStringValues $resourceTypeName $resourceApiTypeName = (($resourceType -split '/', 3) | Select-Object -Index 1) - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ResourceApiTypeName' -StringValues $resourceApiTypeName -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ResourceApiTypeName' -LogStringValues $resourceApiTypeName } $jqRemoveTemplate = Get-AzOpsTemplateFile -File (Join-Path $providerNamespace -ChildPath "$resourceTypeName.jq") -Fallback "generic.jq" - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Jq.Remove' -StringValues $jqRemoveTemplate -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Jq.Remove' -LogStringValues $jqRemoveTemplate # If we were able to determine resourceType, apply filter and write template or template parameter files based on output filename. $object = $Resource | ConvertTo-Json -Depth 100 -EnumsAsStrings | jq -r -f $jqRemoveTemplate | ConvertFrom-Json @@ -199,21 +202,19 @@ else { if ($generateTemplateParameter) { #region Generating Template Parameter - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplateParameter' -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplateParameter' $jqJsonTemplate = Get-AzOpsTemplateFile -File (Join-Path $providerNamespace -ChildPath "$resourceTypeName.parameters.jq") -Fallback "template.parameters.jq" - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Jq.Template' -StringValues $jqJsonTemplate -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Jq.Template' -LogStringValues $jqJsonTemplate $object = ($object | ConvertTo-Json -Depth 100 -EnumsAsStrings | jq -r '--sort-keys' | jq -r -f $jqJsonTemplate | ConvertFrom-Json) #endregion } else { #region Generating Template - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate' -StringValues "$true" -FunctionName 'ConvertTo-AzOpsState' - + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate' -LogStringValues "$true" $jqJsonTemplate = Get-AzOpsTemplateFile -File (Join-Path $providerNamespace -ChildPath "$resourceTypeName.template.jq") -Fallback "template.jq" - - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Jq.Template' -StringValues $jqJsonTemplate -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Jq.Template' -LogStringValues $jqJsonTemplate $object = ($object | ConvertTo-Json -Depth 100 -EnumsAsStrings | jq -r '--sort-keys' | jq -r -f $jqJsonTemplate | ConvertFrom-Json) #endregion @@ -233,12 +234,12 @@ } else { $apiVersion = $gaApiVersion | Select-Object -First 1 } - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ApiVersion' -StringValues $resourceType, $apiVersion -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ApiVersion' -LogStringValues $resourceType, $apiVersion $object.resources[0].apiVersion = $apiVersion $object.resources[0].type = $resourceType } else { - Write-PSFMessage -Level Warning -String 'ConvertTo-AzOpsState.GenerateTemplate.NoApiVersion' -StringValues $resourceType -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Warning -LogString 'ConvertTo-AzOpsState.GenerateTemplate.NoApiVersion' -LogStringValues $resourceType } #endregion @@ -247,17 +248,17 @@ if ($resourceType -eq "Microsoft.Management/managementGroups/subscriptions") { $resourceName = (((New-AzOpsScope -Scope $Resource.Id).ManagementGroup) + "/" + $Resource.Name) $object.resources[0].name = $resourceName - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.GenerateTemplate.ChildResource' -StringValues $resourceName -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.GenerateTemplate.ChildResource' -LogStringValues $resourceName } #endregion } - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Exporting' -StringValues $objectFilePath -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Exporting' -LogStringValues $objectFilePath ConvertTo-Json -InputObject $object -Depth 100 -EnumsAsStrings | Set-Content -Path ([WildcardPattern]::Escape($objectFilePath)) -Encoding UTF8 -Force } } else { - Write-PSFMessage -Level Verbose -String 'ConvertTo-AzOpsState.Exporting.Default' -StringValues $objectFilePath -FunctionName 'ConvertTo-AzOpsState' + Write-AzOpsMessage -LogLevel Debug -LogString 'ConvertTo-AzOpsState.Exporting.Default' -LogStringValues $objectFilePath if ($ReturnObject) { return $Resource } else { ConvertTo-Json -InputObject $Resource -Depth 100 -EnumsAsStrings | Set-Content -Path ([WildcardPattern]::Escape($objectFilePath)) -Encoding UTF8 -Force diff --git a/src/internal/functions/Get-AzOpsCurrentPrincipal.ps1 b/src/internal/functions/Get-AzOpsCurrentPrincipal.ps1 index 3849c320..5c37d193 100644 --- a/src/internal/functions/Get-AzOpsCurrentPrincipal.ps1 +++ b/src/internal/functions/Get-AzOpsCurrentPrincipal.ps1 @@ -17,7 +17,7 @@ ) process { - Write-PSFMessage -Level InternalComment -String 'Get-AzOpsCurrentPrincipal.AccountType' -StringValues $AzContext.Account.Type + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsCurrentPrincipal.AccountType' -LogStringValues $AzContext.Account.Type switch ($AzContext.Account.Type) { 'User' { @@ -32,7 +32,7 @@ $principalObject = Get-AzADServicePrincipal -ApplicationId $AzContext.Account.Id } } - Write-PSFMessage -Level InternalComment -String 'Get-AzOpsCurrentPrincipal.PrincipalId' -StringValues $principalObject.Id + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsCurrentPrincipal.PrincipalId' -LogStringValues $principalObject.Id return $principalObject } } \ No newline at end of file diff --git a/src/internal/functions/Get-AzOpsManagementGroup.ps1 b/src/internal/functions/Get-AzOpsManagementGroup.ps1 index f143a235..9a416630 100644 --- a/src/internal/functions/Get-AzOpsManagementGroup.ps1 +++ b/src/internal/functions/Get-AzOpsManagementGroup.ps1 @@ -42,7 +42,7 @@ $groupObject = Get-AzManagementGroup -GroupId $ManagementGroup -Expand -WarningAction SilentlyContinue } catch { - Write-PSFMessage -Level Error -String 'Get-AzOpsManagementGroup.Failed' -StringValues $ManagementGroup + Write-AzOpsMessage -LogLevel Error -LogString 'Get-AzOpsManagementGroup.Failed' -LogStringValues $ManagementGroup throw } if ($PartialDiscovery) { diff --git a/src/internal/functions/Get-AzOpsPim.ps1 b/src/internal/functions/Get-AzOpsPim.ps1 index e94f4dcc..8caa0b67 100644 --- a/src/internal/functions/Get-AzOpsPim.ps1 +++ b/src/internal/functions/Get-AzOpsPim.ps1 @@ -19,7 +19,7 @@ process { # Process RoleEligibilitySchedule - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'RoleEligibilitySchedule', $scopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'RoleEligibilitySchedule', $scopeObject.Scope $roleEligibilityScheduleRequest = Get-AzOpsRoleEligibilityScheduleRequest -ScopeObject $ScopeObject if ($roleEligibilityScheduleRequest) { $roleEligibilityScheduleRequest | ConvertTo-AzOpsState -StatePath $StatePath diff --git a/src/internal/functions/Get-AzOpsPolicy.ps1 b/src/internal/functions/Get-AzOpsPolicy.ps1 index 34f2e2e2..15ae5ab8 100644 --- a/src/internal/functions/Get-AzOpsPolicy.ps1 +++ b/src/internal/functions/Get-AzOpsPolicy.ps1 @@ -36,7 +36,7 @@ process { if (-not $ResourceGroup) { # Process policy definitions - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'Policy Definitions', $scopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'Policy Definitions', $scopeObject.Scope $policyDefinitions = Get-AzOpsPolicyDefinition -ScopeObject $ScopeObject -Subscription $Subscription $policyDefinitionsClean = @() foreach ($policyDefinition in $policyDefinitions) { @@ -46,12 +46,12 @@ $policyDefinitionsClean | ConvertTo-AzOpsState -StatePath $StatePath # Process policy set definitions (initiatives) - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'Policy Set Definitions', $ScopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'Policy Set Definitions', $ScopeObject.Scope $policySetDefinitions = Get-AzOpsPolicySetDefinition -ScopeObject $ScopeObject -Subscription $Subscription $policySetDefinitions | ConvertTo-AzOpsState -StatePath $StatePath } # Process policy assignments - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'Policy Assignments', $ScopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'Policy Assignments', $ScopeObject.Scope $policyAssignments = Get-AzOpsPolicyAssignment -ScopeObject $ScopeObject -Subscription $Subscription -SubscriptionsToIncludeResourceGroups $SubscriptionsToIncludeResourceGroups -ResourceGroup $ResourceGroup $policyAssignments | ConvertTo-AzOpsState -StatePath $StatePath } diff --git a/src/internal/functions/Get-AzOpsPolicyAssignment.ps1 b/src/internal/functions/Get-AzOpsPolicyAssignment.ps1 index 7317ed08..3327d6cd 100644 --- a/src/internal/functions/Get-AzOpsPolicyAssignment.ps1 +++ b/src/internal/functions/Get-AzOpsPolicyAssignment.ps1 @@ -40,7 +40,7 @@ return } if ($ScopeObject.Type -eq 'managementGroups') { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyAssignment.ManagementGroup' -StringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyAssignment.ManagementGroup' -LogStringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject if ((-not $SubscriptionsToIncludeResourceGroups) -or (-not $ResourceGroups)) { $query = "policyresources | where type == 'microsoft.authorization/policyassignments' and resourceGroup == '' and subscriptionId == '' | order by ['id'] asc" Search-AzOpsAzGraph -ManagementGroupName $ScopeObject.Name -Query $query -ErrorAction Stop @@ -48,17 +48,17 @@ } if ($Subscription) { if ($SubscriptionsToIncludeResourceGroups -and $ResourceGroup) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyAssignment.Subscription' -StringValues $SubscriptionsToIncludeResourceGroups.count -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyAssignment.Subscription' -LogStringValues $SubscriptionsToIncludeResourceGroups.count -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policyassignments' and resourceGroup != '' | order by ['id'] asc" Search-AzOpsAzGraph -Subscription $SubscriptionsToIncludeResourceGroups -Query $query -ErrorAction Stop } elseif ($ResourceGroup) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyAssignment.ResourceGroup' -StringValues $Subscription.count -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyAssignment.ResourceGroup' -LogStringValues $Subscription.count -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policyassignments' and resourceGroup != '' | order by ['id'] asc" Search-AzOpsAzGraph -Subscription $Subscription -Query $query -ErrorAction Stop } else { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyAssignment.Subscription' -StringValues $Subscription.count -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyAssignment.Subscription' -LogStringValues $Subscription.count -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policyassignments' and resourceGroup == '' | order by ['id'] asc" Search-AzOpsAzGraph -Subscription $Subscription -Query $query -ErrorAction Stop } diff --git a/src/internal/functions/Get-AzOpsPolicyDefinition.ps1 b/src/internal/functions/Get-AzOpsPolicyDefinition.ps1 index 95fd62bf..dece890c 100644 --- a/src/internal/functions/Get-AzOpsPolicyDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsPolicyDefinition.ps1 @@ -30,12 +30,12 @@ return } if ($ScopeObject.Type -eq 'managementGroups') { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyDefinition.ManagementGroup' -StringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyDefinition.ManagementGroup' -LogStringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policydefinitions' and properties.policyType == 'Custom' and subscriptionId == '' | order by ['id'] asc" Search-AzOpsAzGraph -ManagementGroupName $ScopeObject.Name -Query $query -ErrorAction Stop } if ($Subscription) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyDefinition.Subscription' -StringValues $Subscription.count -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyDefinition.Subscription' -LogStringValues $Subscription.count -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policydefinitions' and properties.policyType == 'Custom' | order by ['id'] asc" Search-AzOpsAzGraph -Subscription $Subscription -Query $query -ErrorAction Stop } diff --git a/src/internal/functions/Get-AzOpsPolicyExemption.ps1 b/src/internal/functions/Get-AzOpsPolicyExemption.ps1 index 0e204557..a32e3cb0 100644 --- a/src/internal/functions/Get-AzOpsPolicyExemption.ps1 +++ b/src/internal/functions/Get-AzOpsPolicyExemption.ps1 @@ -27,13 +27,13 @@ switch ($ScopeObject.Type) { managementGroups { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyExemption.ManagementGroup' -StringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyExemption.ManagementGroup' -LogStringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject } subscriptions { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyExemption.Subscription' -StringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyExemption.Subscription' -LogStringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription -Target $ScopeObject } resourcegroups { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicyExemption.ResourceGroup' -StringValues $ScopeObject.ResourceGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicyExemption.ResourceGroup' -LogStringValues $ScopeObject.ResourceGroup -Target $ScopeObject } } try { @@ -46,7 +46,7 @@ } -RetryCount 3 -RetryWait 5 -RetryType Exponential -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning -Message $_ -FunctionName "Get-AzOpsPolicyExemption" + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsPolicyExemption.Failed' -LogStringValues $ScopeObject.Scope } } diff --git a/src/internal/functions/Get-AzOpsPolicySetDefinition.ps1 b/src/internal/functions/Get-AzOpsPolicySetDefinition.ps1 index 2e141ccc..dc568e05 100644 --- a/src/internal/functions/Get-AzOpsPolicySetDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsPolicySetDefinition.ps1 @@ -30,12 +30,12 @@ return } if ($ScopeObject.Type -eq 'managementGroups') { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicySetDefinition.ManagementGroup' -StringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicySetDefinition.ManagementGroup' -LogStringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policysetdefinitions' and properties.policyType == 'Custom' and subscriptionId == '' | order by ['id'] asc" Search-AzOpsAzGraph -ManagementGroupName $ScopeObject.Name -Query $query -ErrorAction Stop } if ($Subscription) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsPolicySetDefinition.Subscription' -StringValues $Subscription.count -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsPolicySetDefinition.Subscription' -LogStringValues $Subscription.count -Target $ScopeObject $query = "policyresources | where type == 'microsoft.authorization/policysetdefinitions' and properties.policyType == 'Custom' | order by ['id'] asc" Search-AzOpsAzGraph -Subscription $Subscription -Query $query -ErrorAction Stop } diff --git a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 index aaf7b8e5..9e7bbc92 100644 --- a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 @@ -105,30 +105,25 @@ } process { - Write-PSFMessage -Level Important -String 'Get-AzOpsResourceDefinition.Processing' -StringValues $Scope + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsResourceDefinition.Processing' -LogStringValues $Scope try { $scopeObject = New-AzOpsScope -Scope $Scope -StatePath $StatePath -ErrorAction Stop - # Logging output metadata - $msgCommon = @{ - FunctionName = 'Get-AzOpsResourceDefinition' - Target = $ScopeObject - } } catch { - Write-PSFMessage -Level Warning -String 'Get-AzOpsResourceDefinition.Processing.NotFound' -StringValues $Scope + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.Processing.NotFound' -LogStringValues $Scope return } if ($scopeObject.Type -notin 'subscriptions', 'managementGroups') { - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Finished' -StringValues $scopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Finished' -LogStringValues $scopeObject.Scope return } switch ($scopeObject.Type) { subscriptions { - Write-PSFMessage -Level Important @msgCommon -String 'Get-AzOpsResourceDefinition.Subscription.Processing' -StringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsResourceDefinition.Subscription.Processing' -LogStringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription -Target $ScopeObject $subscriptions = Get-AzSubscription -SubscriptionId $scopeObject.Name | Where-Object { "/subscriptions/$($_.Id)" -in $script:AzOpsSubscriptions.id } } managementGroups { - Write-PSFMessage -Level Important @msgCommon -String 'Get-AzOpsResourceDefinition.ManagementGroup.Processing' -StringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsResourceDefinition.ManagementGroup.Processing' -LogStringValues $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup -Target $ScopeObject $query = "resourcecontainers | where type == 'microsoft.management/managementgroups' | order by ['id'] asc" $managementgroups = Search-AzOpsAzGraph -ManagementGroupName $scopeObject.Name -Query $query -ErrorAction Stop | Where-Object { $_.id -in $script:AzOpsAzManagementGroup.Id } $subscriptions = Get-AzOpsNestedSubscription -Scope $scopeObject.Name @@ -166,6 +161,7 @@ } } } + Clear-PSFMessage } } } @@ -212,16 +208,17 @@ } } } + Clear-PSFMessage } #endregion Process subscription scope in parallel #region Process Resource Groups if ($SkipResourceGroup -or (-not $subscriptions)) { if ($SkipResourceGroup) { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.SkippingResourceGroup' + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.SkippingResourceGroup' -Target $ScopeObject } else { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.Subscription.NotFound' + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.Subscription.NotFound' -Target $ScopeObject } } else { @@ -276,9 +273,10 @@ } } } + Clear-PSFMessage } else { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.NoResourceGroup' -StringValues $scopeObject.Name + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.NoResourceGroup' -LogStringValues $scopeObject.Name -Target $ScopeObject } # Process Policies at Resource Group scope if (-not $SkipPolicy) { @@ -291,7 +289,7 @@ } # Process Resources at Resource Group scope if (-not $SkipResource) { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery' -StringValues $scopeObject.Name + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery' -LogStringValues $scopeObject.Name -Target $ScopeObject try { $SkipResourceType | ForEach-Object { $skipResourceTypes += ($(if($skipResourceTypes){","}) + "'" + $_ + "'") } $query = "resources | where type !in~ ($skipResourceTypes)" @@ -307,24 +305,24 @@ $resourcesBase = Search-AzOpsAzGraph -Subscription $subscriptions -Query $query -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning @msgCommon -String 'Get-AzOpsResourceDefinition.Processing.Resource.Warning' -StringValues $scopeObject.Name + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.Processing.Resource.Warning' -LogStringValues $scopeObject.Name -Target $ScopeObject } if ($resourcesBase) { $resources = @() foreach ($resource in $resourcesBase) { if ($resourceGroups | Where-Object { $_.name -eq $resource.resourceGroup -and $_.subscriptionId -eq $resource.subscriptionId }) { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.Processing.Resource' -StringValues $resource.name, $resource.resourcegroup -Target $resource + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Resource' -LogStringValues $resource.name, $resource.resourcegroup -Target $resource $resources += $resource ConvertTo-AzOpsState -Resource $resource -StatePath $Statepath } } } else { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery.NotFound' -StringValues $scopeObject.Name + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery.NotFound' -LogStringValues $scopeObject.Name -Target $ScopeObject } } else { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.SkippingResources' + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.SkippingResources' -Target $ScopeObject } # Process resources as scope in parallel, look for childResource if (-not $SkipResource -and -not $SkipChildResource) { @@ -365,7 +363,9 @@ $resourceGroup = $using:resourceGroups | Where-Object {$_.subscriptionId -eq $resource.subscriptionId -and $_.name -eq $resource.resourceGroup} foreach ($exportResource in $exportResources) { if (-not(($resource.name -eq $exportResource.name) -and ($resource.type -eq $exportResource.type))) { - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.ChildResource' -StringValues $exportResource.name, $resource.resourceGroup -Target $exportResource + & $azOps { + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.ChildResource' -LogStringValues $exportResource.name, $resource.resourceGroup -FunctionName "Get-AzOpsResourceDefinition" -ModuleName "AzOps" -Target $exportResource + } $ChildResource = @{ resourceProvider = $exportResource.type -replace '/', '_' resourceName = $exportResource.name -replace '/', '_' @@ -382,18 +382,21 @@ } } catch { - Write-PSFMessage -Level Warning -String 'Get-AzOpsResourceDefinition.ChildResource.Warning' -StringValues $resource.resourceGroup, $_ + & $azOps { + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.ChildResource.Warning' -LogStringValues $resource.resourceGroup, $_ -FunctionName "Get-AzOpsResourceDefinition" -ModuleName "AzOps" + } } if (Test-Path -Path $tempExportPath) { Remove-Item -Path $tempExportPath } } + Clear-PSFMessage } else { - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.SkippingChildResources' + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.SkippingChildResources' -Target $ScopeObject } } #endregion Process Resource Groups - Write-PSFMessage -Level Verbose @msgCommon -String 'Get-AzOpsResourceDefinition.Finished' -StringValues $scopeObject.Scope + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.Finished' -LogStringValues $scopeObject.Scope -Target $ScopeObject } } \ No newline at end of file diff --git a/src/internal/functions/Get-AzOpsResourceLock.ps1 b/src/internal/functions/Get-AzOpsResourceLock.ps1 index 22df743d..d5709c52 100644 --- a/src/internal/functions/Get-AzOpsResourceLock.ps1 +++ b/src/internal/functions/Get-AzOpsResourceLock.ps1 @@ -30,11 +30,11 @@ switch ($ScopeObject.Type) { subscriptions { # ScopeObject is a subscription - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceLock.Subscription' -StringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceLock.Subscription' -LogStringValues $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription -Target $ScopeObject } resourcegroups { # ScopeObject is a resourcegroup - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceLock.ResourceGroup' -StringValues $ScopeObject.ResourceGroup -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceLock.ResourceGroup' -LogStringValues $ScopeObject.ResourceGroup -Target $ScopeObject } } try { @@ -47,7 +47,7 @@ } -RetryCount 3 -RetryWait 5 -RetryType Exponential -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning -Message $_ -FunctionName "Get-AzOpsResourceLock" + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceLock.Failed' -LogStringValues $_ } if ($resourceLocks) { # Process each resource lock diff --git a/src/internal/functions/Get-AzOpsRole.ps1 b/src/internal/functions/Get-AzOpsRole.ps1 index f05edca5..e47a967d 100644 --- a/src/internal/functions/Get-AzOpsRole.ps1 +++ b/src/internal/functions/Get-AzOpsRole.ps1 @@ -19,14 +19,14 @@ process { # Process role definitions - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'Role Definitions', $ScopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'Role Definitions', $ScopeObject.Scope $roleDefinitions = Get-AzOpsRoleDefinition -ScopeObject $ScopeObject if ($roleDefinitions) { $roleDefinitions | ConvertTo-AzOpsState -StatePath $StatePath } # Process role assignments - Write-PSFMessage -Level Verbose -String 'Get-AzOpsResourceDefinition.Processing.Detail' -StringValues 'Role Assignments', $ScopeObject.Scope + Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Detail' -LogStringValues 'Role Assignments', $ScopeObject.Scope $roleAssignments = Get-AzOpsRoleAssignment -ScopeObject $ScopeObject if ($roleAssignments) { $roleAssignments | ConvertTo-AzOpsState -StatePath $StatePath diff --git a/src/internal/functions/Get-AzOpsRoleAssignment.ps1 b/src/internal/functions/Get-AzOpsRoleAssignment.ps1 index ce39fd7e..75329232 100644 --- a/src/internal/functions/Get-AzOpsRoleAssignment.ps1 +++ b/src/internal/functions/Get-AzOpsRoleAssignment.ps1 @@ -20,7 +20,7 @@ ) process { - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleAssignment.Processing' -StringValues $ScopeObject -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleAssignment.Processing' -LogStringValues $ScopeObject -Target $ScopeObject $apiVersion = (($script:AzOpsResourceProvider | Where-Object {$_.ProviderNamespace -eq 'Microsoft.Authorization'}).ResourceTypes | Where-Object {$_.ResourceTypeName -eq 'roleAssignments'}).ApiVersions | Select-Object -First 1 $path = "$($scopeObject.Scope)/providers/Microsoft.Authorization/roleAssignments?api-version=$apiVersion&`$filter=atScope()" try { @@ -34,13 +34,13 @@ } -RetryCount 3 -RetryWait 5 -RetryType Exponential -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning -Message $_ -FunctionName "Get-AzOpsRoleAssignment" + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsRoleAssignment.Processing.Failed' -LogStringValues $_ } if ($roleAssignments) { $roleAssignmentMatch = @() foreach ($roleAssignment in $roleAssignments) { if ($roleAssignment.properties.scope -eq $ScopeObject.Scope) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleAssignment.Assignment' -StringValues $roleAssignment.id, $roleAssignment.properties.roleDefinitionId -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleAssignment.Assignment' -LogStringValues $roleAssignment.id, $roleAssignment.properties.roleDefinitionId -Target $ScopeObject $roleAssignmentMatch += [PSCustomObject]@{ id = $roleAssignment.id name = $roleAssignment.name diff --git a/src/internal/functions/Get-AzOpsRoleDefinition.ps1 b/src/internal/functions/Get-AzOpsRoleDefinition.ps1 index 6169d173..0413b2e4 100644 --- a/src/internal/functions/Get-AzOpsRoleDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsRoleDefinition.ps1 @@ -20,7 +20,7 @@ ) process { - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleDefinition.Processing' -StringValues $ScopeObject -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleDefinition.Processing' -LogStringValues $ScopeObject -Target $ScopeObject $apiVersion = (($script:AzOpsResourceProvider | Where-Object {$_.ProviderNamespace -eq 'Microsoft.Authorization'}).ResourceTypes | Where-Object {$_.ResourceTypeName -eq 'roleDefinitions'}).ApiVersions | Select-Object -First 1 $path = "$($scopeObject.Scope)/providers/Microsoft.Authorization/roleDefinitions?api-version=$apiVersion&`$filter=type+eq+'CustomRole'" try { @@ -34,13 +34,13 @@ } -RetryCount 3 -RetryWait 5 -RetryType Exponential -ErrorAction Stop } catch { - Write-PSFMessage -Level Warning -Message $_ -FunctionName "Get-AzOpsRoleDefinition" + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsRoleDefinition.Processing.Failed' -LogStringValues $_ } if ($roleDefinitions) { $roleDefinitionsMatch = @() foreach ($roleDefinition in $roleDefinitions) { if ($roleDefinition.properties.assignableScopes -eq $ScopeObject.Scope) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleDefinition.Definition' -StringValues $roleDefinition.id -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleDefinition.Definition' -LogStringValues $roleDefinition.id -Target $ScopeObject $roleDefinitionsMatch += [PSCustomObject]@{ # Removing the Trailing slash to ensure that '/' is not appended twice when adding '/providers/xxx'. # Example: '/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/' is a valid assignment scope. diff --git a/src/internal/functions/Get-AzOpsRoleEligibilityScheduleRequest.ps1 b/src/internal/functions/Get-AzOpsRoleEligibilityScheduleRequest.ps1 index df475ec7..ba32e11d 100644 --- a/src/internal/functions/Get-AzOpsRoleEligibilityScheduleRequest.ps1 +++ b/src/internal/functions/Get-AzOpsRoleEligibilityScheduleRequest.ps1 @@ -25,14 +25,14 @@ } # Process RoleEligibilitySchedule which is used to construct AzOpsRoleEligibilityScheduleRequest - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleEligibilityScheduleRequest.Processing' -StringValues $ScopeObject.Scope -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleEligibilityScheduleRequest.Processing' -LogStringValues $ScopeObject.Scope -Target $ScopeObject $roleEligibilitySchedules = Get-AzRoleEligibilitySchedule -Scope $ScopeObject.Scope -WarningAction SilentlyContinue | Where-Object {$_.Scope -eq $ScopeObject.Scope} if ($roleEligibilitySchedules) { foreach ($roleEligibilitySchedule in $roleEligibilitySchedules) { # Process roleEligibilitySchedule together with RoleEligibilityScheduleRequest $roleEligibilityScheduleRequest = Get-AzRoleEligibilityScheduleRequest -Scope $ScopeObject.Scope -Name $roleEligibilitySchedule.Name -ErrorAction SilentlyContinue if ($roleEligibilityScheduleRequest) { - Write-PSFMessage -Level Debug -String 'Get-AzOpsRoleEligibilityScheduleRequest.Assignment' -StringValues $roleEligibilitySchedule.Name -Target $ScopeObject + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsRoleEligibilityScheduleRequest.Assignment' -LogStringValues $roleEligibilitySchedule.Name -Target $ScopeObject # Construct AzOpsRoleEligibilityScheduleRequest by combining information from roleEligibilitySchedule and roleEligibilityScheduleRequest [AzOpsRoleEligibilityScheduleRequest]::new($roleEligibilitySchedule, $roleEligibilityScheduleRequest) } diff --git a/src/internal/functions/Get-AzOpsSubscription.ps1 b/src/internal/functions/Get-AzOpsSubscription.ps1 index 884d00b9..fab13ae0 100644 --- a/src/internal/functions/Get-AzOpsSubscription.ps1 +++ b/src/internal/functions/Get-AzOpsSubscription.ps1 @@ -38,8 +38,8 @@ ) process { - Write-PSFMessage -Level Important -String 'Get-AzOpsSubscription.Excluded.States' -StringValues ($ExcludedStates -join ',') - Write-PSFMessage -Level Important -String 'Get-AzOpsSubscription.Excluded.Offers' -StringValues ($ExcludedOffers -join ',') + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsSubscription.Excluded.States' -LogStringValues ($ExcludedStates -join ',') + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsSubscription.Excluded.Offers' -LogStringValues ($ExcludedOffers -join ',') $nextLink = "/subscriptions?api-version=$ApiVersion" $allSubscriptionsResults = do { @@ -54,19 +54,19 @@ $_.subscriptionPolicies.quotaId -notin $ExcludedOffers } if (-not $includedSubscriptions) { - Write-PSFMessage -Level Warning -String 'Get-AzOpsSubscription.NoSubscriptions' -Tag failed + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsSubscription.NoSubscriptions' return } - Write-PSFMessage -Level Important -String 'Get-AzOpsSubscription.Subscriptions.Found' -StringValues $allSubscriptionsResults.Count + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsSubscription.Subscriptions.Found' -LogStringValues $allSubscriptionsResults.Count if ($allSubscriptionsResults.Count -gt $includedSubscriptions.Count) { - Write-PSFMessage -Level Important -String 'Get-AzOpsSubscription.Subscriptions.Excluded' -StringValues ($allSubscriptionsResults.Count - $includedSubscriptions.Count) + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsSubscription.Subscriptions.Excluded' -LogStringValues ($allSubscriptionsResults.Count - $includedSubscriptions.Count) } if ($includedSubscriptions | Where-Object State -EQ PastDue) { - Write-PSFMessage -Level Warning -String 'Get-AzOpsSubscription.Subscriptions.PastDue' -StringValues ($includedSubscriptions | Where-Object State -EQ PastDue).Count + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsSubscription.Subscriptions.PastDue' -LogStringValues ($includedSubscriptions | Where-Object State -EQ PastDue).Count } - Write-PSFMessage -Level Important -String 'Get-AzOpsSubscription.Subscriptions.Included' -StringValues $includedSubscriptions.Count + Write-AzOpsMessage -LogLevel Important -LogString 'Get-AzOpsSubscription.Subscriptions.Included' -LogStringValues $includedSubscriptions.Count -Metric $includedSubscriptions.Count -MetricName 'Subscription Count' $includedSubscriptions } diff --git a/src/internal/functions/Get-AzOpsTemplateFile.ps1 b/src/internal/functions/Get-AzOpsTemplateFile.ps1 index 195003c3..df6c0320 100644 --- a/src/internal/functions/Get-AzOpsTemplateFile.ps1 +++ b/src/internal/functions/Get-AzOpsTemplateFile.ps1 @@ -36,14 +36,14 @@ ) process { - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing' -StringValues $File + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing' -LogStringValues $File # Evaluate JqTemplate Conditions if ($SkipCustomJqTemplate) { # Use default module templates only - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Path' -StringValues $File, $JqTemplatePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Path' -LogStringValues $File, $JqTemplatePath if ($Fallback) { # Process with Fallback - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Fallback' -StringValues $File, $Fallback + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Fallback' -LogStringValues $File, $Fallback $return = (Test-Path -Path (Join-Path $JqTemplatePath -ChildPath $File) -PathType Leaf) ? (Get-Item -Path (Join-Path $JqTemplatePath -ChildPath $File) -ErrorAction SilentlyContinue): (Get-Item -Path (Join-Path $JqTemplatePath -ChildPath $Fallback) -ErrorAction SilentlyContinue) @@ -57,16 +57,16 @@ } else { # Use custom templates - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Path' -StringValues $File, $CustomJqTemplatePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Path' -LogStringValues $File, $CustomJqTemplatePath if ($Fallback) { # Process with Fallback - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Fallback' -StringValues $File, $Fallback + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Fallback' -LogStringValues $File, $Fallback $return = (Test-Path -Path (Join-Path $CustomJqTemplatePath -ChildPath $File) -PathType Leaf) ? (Get-Item -Path (Join-Path $CustomJqTemplatePath -ChildPath $File) -ErrorAction SilentlyContinue): (Get-Item -Path (Join-Path $CustomJqTemplatePath -ChildPath $Fallback) -ErrorAction SilentlyContinue) if (-not $return) { # Use default templates since no custom templates was found - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Path' -StringValues $File, $JqTemplatePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Path' -LogStringValues $File, $JqTemplatePath $return = (Test-Path -Path (Join-Path $JqTemplatePath -ChildPath $File) -PathType Leaf) ? (Get-Item -Path (Join-Path $JqTemplatePath -ChildPath $File) -ErrorAction SilentlyContinue): (Get-Item -Path (Join-Path $JqTemplatePath -ChildPath $Fallback) -ErrorAction SilentlyContinue) @@ -79,7 +79,7 @@ } if (-not $return) { # Use default templates since no custom templates was found - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Path' -StringValues $File, $JqTemplatePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Get-AzOpsTemplateFile.Processing.Path' -LogStringValues $File, $JqTemplatePath if (Test-Path -Path (Join-Path $JqTemplatePath -ChildPath $File) -PathType Leaf) { $return = (Get-Item -Path (Join-Path $JqTemplatePath -ChildPath $File) -ErrorAction SilentlyContinue) } @@ -89,12 +89,12 @@ if ($return) { # Template file found $return = ($return | Select-Object -First 1).VersionInfo.FileName - Write-PSFMessage -Level Verbose -String 'Get-AzOpsTemplateFile.Processing.Found' -StringValues $return + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsTemplateFile.Processing.Found' -LogStringValues $return return $return } else { # No template file found, throw - Write-PSFMessage -Level Error -String 'Get-AzOpsTemplateFile.Processing.NotFound' -StringValues $File + Write-AzOpsMessage -LogLevel Error -LogString 'Get-AzOpsTemplateFile.Processing.NotFound' -LogStringValues $File throw } } diff --git a/src/internal/functions/Invoke-AzOpsNativeCommand.ps1 b/src/internal/functions/Invoke-AzOpsNativeCommand.ps1 index 139bc9a3..f52027b5 100644 --- a/src/internal/functions/Invoke-AzOpsNativeCommand.ps1 +++ b/src/internal/functions/Invoke-AzOpsNativeCommand.ps1 @@ -38,7 +38,7 @@ if (-not $Quiet -and $output) { $output | Out-String -NoNewLine | ForEach-Object { - Write-PSFMessage -Level Debug -Message $_ + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsNativeCommand' -LogStringValues $ScriptBlock, $_ } $output } diff --git a/src/internal/functions/Invoke-AzOpsRestMethod.ps1 b/src/internal/functions/Invoke-AzOpsRestMethod.ps1 index 72988ee8..c991bc98 100644 --- a/src/internal/functions/Invoke-AzOpsRestMethod.ps1 +++ b/src/internal/functions/Invoke-AzOpsRestMethod.ps1 @@ -21,7 +21,7 @@ process { # Process Path with given Method - Write-PSFMessage -Level Debug -String 'Invoke-AzOpsRestMethod.Processing' -StringValues $Path + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsRestMethod.Processing' -LogStringValues $Path $allresults = do { try { $results = ((Invoke-AzRestMethod -Path $Path -Method $Method -ErrorAction Stop).Content | ConvertFrom-Json -Depth 100) @@ -30,14 +30,14 @@ if ($results.StatusCode -eq '429' -or $results.StatusCode -like '5*') { $results.Headers.GetEnumerator() | ForEach-Object { if ($_.key -eq 'Retry-After') { - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsRestMethod.Processing.RateLimit' -StringValues $Path, $_.value + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsRestMethod.Processing.RateLimit' -LogStringValues $Path, $_.value Start-Sleep -Seconds $_.value } } } } catch { - Write-PSFMessage -Level Error -String 'Invoke-AzOpsRestMethod.Processing.Error' -StringValues $_, $Path + Write-AzOpsMessage -LogLevel Error -LogString 'Invoke-AzOpsRestMethod.Processing.Error' -LogStringValues $_, $Path } } while ($path) diff --git a/src/internal/functions/Invoke-AzOpsScriptBlock.ps1 b/src/internal/functions/Invoke-AzOpsScriptBlock.ps1 index 647f0eb2..89d60c13 100644 --- a/src/internal/functions/Invoke-AzOpsScriptBlock.ps1 +++ b/src/internal/functions/Invoke-AzOpsScriptBlock.ps1 @@ -69,14 +69,14 @@ } catch { if ($count -lt $RetryCount) { - Write-PSFMessage -Level Debug -String 'Invoke-AzOpsScriptBlock.Failed.WillRetry' -StringValues $count, $RetryCount -ErrorRecord $_ -Data $data + Write-AzOpsMessage -LogLevel Debug -LogString 'Invoke-AzOpsScriptBlock.Failed.WillRetry' -LogStringValues $ScriptBlock, $count, $RetryCount -ErrorRecord $_ -Data $data switch ($RetryType) { Linear { Start-Sleep -Seconds $RetryWait } Exponential { Start-Sleep -Seconds ([math]::Pow($RetryWait, $count)) } } continue } - Write-PSFMessage -Level Warning -String 'Invoke-AzOpsScriptBlock.Failed.GivingUp' -StringValues $count, $RetryCount -ErrorRecord $_ -Data $data + Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsScriptBlock.Failed.GivingUp' -LogStringValues $ScriptBlock, $count, $RetryCount -ErrorRecord $_ -Data $data throw } } diff --git a/src/internal/functions/New-AzOpsDeployment.ps1 b/src/internal/functions/New-AzOpsDeployment.ps1 index b6577216..926ccdde 100644 --- a/src/internal/functions/New-AzOpsDeployment.ps1 +++ b/src/internal/functions/New-AzOpsDeployment.ps1 @@ -58,7 +58,7 @@ ) process { - Write-PSFMessage -Level Important -String 'New-AzOpsDeployment.Processing' -StringValues $DeploymentName, $TemplateFilePath, $TemplateParameterFilePath, $Mode -Target $TemplateFilePath + Write-AzOpsMessage -LogLevel Important -LogString 'New-AzOpsDeployment.Processing' -LogStringValues $DeploymentName, $TemplateFilePath, $TemplateParameterFilePath, $Mode -Target $TemplateFilePath #region Resolve Scope try { @@ -71,11 +71,11 @@ $scopeFound = $true } catch { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.Scope.Failed' -Target $TemplateFilePath -StringValues $TemplateFilePath, $TemplateParameterFilePath -ErrorRecord $_ + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.Scope.Failed' -LogStringValues $TemplateFilePath, $TemplateParameterFilePath -ErrorRecord $_ return } if (-not $scopeObject) { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.Scope.Empty' -Target $TemplateFilePath -StringValues $TemplateFilePath, $TemplateParameterFilePath + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.Scope.Empty' -LogStringValues $TemplateFilePath, $TemplateParameterFilePath return } #endregion Resolve Scope @@ -99,7 +99,7 @@ } # Resource Groups excluding Microsoft.Resources/resourceGroups that needs to be submitted at subscription scope if ($scopeObject.resourcegroup -and $templateContent.resources[0].type -ne 'Microsoft.Resources/resourceGroups') { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.ResourceGroup.Processing' -StringValues $scopeObject -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.ResourceGroup.Processing' -LogStringValues $scopeObject -Target $scopeObject Set-AzOpsContext -ScopeObject $scopeObject $whatIfCommand = 'Get-AzResourceGroupDeploymentWhatIfResult' $deploymentCommand = 'New-AzResourceGroupDeployment' @@ -108,21 +108,21 @@ } # Subscriptions elseif ($scopeObject.subscription) { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.Subscription.Processing' -StringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.Subscription.Processing' -LogStringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject Set-AzOpsContext -ScopeObject $scopeObject $whatIfCommand = 'Get-AzSubscriptionDeploymentWhatIfResult' $deploymentCommand = 'New-AzSubscriptionDeployment' } # Management Groups elseif ($scopeObject.managementGroup -and (-not ($scopeObject.StatePath).StartsWith('azopsscope-assume-new-resource_'))) { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.ManagementGroup.Processing' -StringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.ManagementGroup.Processing' -LogStringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject $parameters.ManagementGroupId = $scopeObject.managementgroup $whatIfCommand = 'Get-AzManagementGroupDeploymentWhatIfResult' $deploymentCommand = 'New-AzManagementGroupDeployment' } # Tenant deployments elseif ($scopeObject.type -eq 'root' -and $scopeObject.scope -eq '/') { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.Root.Processing' -StringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.Root.Processing' -LogStringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject $whatIfCommand = 'Get-AzTenantDeploymentWhatIfResult' $deploymentCommand = 'New-AzTenantDeployment' } @@ -140,24 +140,24 @@ if ($parentDirScopeObject -and $parentIdScope -and $parentDirScopeObject.Scope -eq $parentIdScope.Scope -and $parentDirScopeObject.StatePath -eq $parentIdScope.StatePath -and $parentDirScopeObject.Name -eq $parentIdScope.Name) { # Validate directory name match resource information if ((Get-Item -Path $pathDir).Name -eq "$($resource.properties.displayName) ($($resource.name))") { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.Root.Processing' -StringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.Root.Processing' -LogStringValues $defaultDeploymentRegion, $scopeObject -Target $scopeObject $whatIfCommand = 'Get-AzTenantDeploymentWhatIfResult' $deploymentCommand = 'New-AzTenantDeployment' } # Invalid directory name else { - Write-PSFMessage -Level Error -String 'New-AzOpsDeployment.Directory.NotFound' -Target $scopeObject -Tag Error -StringValues (Get-Item -Path $pathDir).Name, "$($resource.properties.displayName) ($($resource.name))" + Write-AzOpsMessage -LogLevel Error -LogString 'New-AzOpsDeployment.Directory.NotFound' -LogStringValues (Get-Item -Path $pathDir).Name, "$($resource.properties.displayName) ($($resource.name))" throw } } # Parent missing else { - Write-PSFMessage -Level Error -String 'New-AzOpsDeployment.Parent.NotFound' -Target $scopeObject -Tag Error -StringValues $addition + Write-AzOpsMessage -LogLevel Error -LogString 'New-AzOpsDeployment.Parent.NotFound' -LogStringValues $addition throw } } else { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.Scope.Unidentified' -Target $scopeObject -StringValues $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.Scope.Unidentified' -LogStringValues $scopeObject $scopeFound = $false } # Proceed with WhatIf or Deployment if scope was found @@ -180,12 +180,12 @@ $resultsErrorMessage = $resultsError.exception.InnerException.Message # Ignore errors for bicep modules if ($resultsErrorMessage -match 'https://aka.ms/resource-manager-parameter-files' -and $true -eq $bicepTemplate) { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.TemplateParameterError' -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.TemplateParameterError' -Target $scopeObject $invalidTemplate = $true } # Handle WhatIf prediction errors elseif ($resultsErrorMessage -match 'DeploymentWhatIfResourceError' -and $resultsErrorMessage -match "The request to predict template deployment") { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.WhatIfWarning' -Target $scopeObject -Tag Error -StringValues $resultsErrorMessage + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.WhatIfWarning' -LogStringValues $resultsErrorMessage -Target $scopeObject if ($parameters.TemplateParameterFile) { $deploymentResult.filePath = $parameters.TemplateFile $deploymentResult.parameterFilePath = $parameters.TemplateParameterFile @@ -197,17 +197,17 @@ } } else { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.WhatIfWarning' -Target $scopeObject -Tag Error -StringValues $resultsErrorMessage + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.WhatIfWarning' -LogStringValues $resultsErrorMessage -Target $scopeObject throw $resultsErrorMessage } } elseif ($results.Error) { - Write-PSFMessage -Level Warning -String 'New-AzOpsDeployment.TemplateError' -StringValues $TemplateFilePath -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsDeployment.TemplateError' -LogStringValues $TemplateFilePath -Target $scopeObject return } else { - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.WhatIfResults' -StringValues ($results | Out-String) -Target $scopeObject - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.WhatIfFile' -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsDeployment.WhatIfResults' -LogStringValues ($results | Out-String) -Target $scopeObject + Write-AzOpsMessage -LogLevel InternalComment -LogString 'New-AzOpsDeployment.WhatIfFile' -Target $scopeObject if ($parameters.TemplateParameterFile) { $deploymentResult.filePath = $parameters.TemplateFile $deploymentResult.parameterFilePath = $parameters.TemplateParameterFile @@ -230,7 +230,7 @@ } else { # Exit deployment - Write-PSFMessage -Level Verbose -String 'New-AzOpsDeployment.SkipDueToWhatIf' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'New-AzOpsDeployment.SkipDueToWhatIf' } } #Return diff --git a/src/internal/functions/New-AzOpsScope.ps1 b/src/internal/functions/New-AzOpsScope.ps1 index 6fef4af1..13802fe6 100644 --- a/src/internal/functions/New-AzOpsScope.ps1 +++ b/src/internal/functions/New-AzOpsScope.ps1 @@ -61,7 +61,7 @@ $StatePath = (Get-PSFConfigValue -FullName 'AzOps.Core.State') ) process { - Write-PSFMessage -Level Debug -String 'New-AzOpsScope.Starting' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'New-AzOpsScope.Starting' switch ($PSCmdlet.ParameterSetName) { scope { diff --git a/src/internal/functions/New-AzOpsStateDeployment.ps1 b/src/internal/functions/New-AzOpsStateDeployment.ps1 index d6c890ba..20339ece 100644 --- a/src/internal/functions/New-AzOpsStateDeployment.ps1 +++ b/src/internal/functions/New-AzOpsStateDeployment.ps1 @@ -33,11 +33,11 @@ } process { - Write-PSFMessage -Level Important -String 'New-AzOpsStateDeployment.Processing' -StringValues $FileName + Write-AzOpsMessage -LogLevel Important -LogString 'New-AzOpsStateDeployment.Processing' -LogStringValues $FileName $scopeObject = New-AzOpsScope -Path (Get-Item -Path $FileName).FullName -StatePath $StatePath if (-not $scopeObject.Type) { - Write-PSFMessage -Level Warning -String 'New-AzOpsStateDeployment.InvalidScope' -StringValues $FileName -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'New-AzOpsStateDeployment.InvalidScope' -LogStringValues $FileName -Target $scopeObject return } #TODO: Clarify whether this exclusion was intentional @@ -45,25 +45,25 @@ #region Process Subscriptions if ($FileName -match '/*.subscription.json$') { - Write-PSFMessage -Level Verbose -String 'New-AzOpsStateDeployment.Subscription' -StringValues $FileName -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsStateDeployment.Subscription' -LogStringValues $FileName -Target $scopeObject $subscription = $subscriptions | Where-Object Name -EQ $scopeObject.subscriptionDisplayName #region Subscription needs to be created if (-not $subscription) { - Write-PSFMessage -Level Important -String 'New-AzOpsStateDeployment.Subscription.New' -StringValues $FileName -Target $scopeObject + Write-AzOpsMessage -LogLevel Important -LogString 'New-AzOpsStateDeployment.Subscription.New' -LogStringValues $FileName -Target $scopeObject if (-not $enrollmentAccounts) { - Write-PSFMessage -Level Error -String 'New-AzOpsStateDeployment.NoEnrollmentAccount' -Target $scopeObject - Write-PSFMessage -Level Error -String 'New-AzOpsStateDeployment.NoEnrollmentAccount.Solution' -Target $scopeObject + Write-AzOpsMessage -LogLevel Error -LogString 'New-AzOpsStateDeployment.NoEnrollmentAccount' -Target $scopeObject + Write-AzOpsMessage -LogLevel Error -LogString 'New-AzOpsStateDeployment.NoEnrollmentAccount.Solution' -Target $scopeObject return } if ($cfgEnrollmentAccount = Get-PSFConfigValue -FullName 'AzOps.Core.EnrollmentAccountPrincipalName') { - Write-PSFMessage -Level Important -String 'New-AzOpsStateDeployment.EnrollmentAccount.Selected' -StringValues $cfgEnrollmentAccount + Write-AzOpsMessage -LogLevel Important -LogString 'New-AzOpsStateDeployment.EnrollmentAccount.Selected' -LogStringValues $cfgEnrollmentAccount $enrollmentAccountObjectId = ($enrollmentAccounts | Where-Object PrincipalName -eq $cfgEnrollmentAccount).ObjectId } else { - Write-PSFMessage -Level Important -String 'New-AzOpsStateDeployment.EnrollmentAccount.First' -StringValues @($enrollmentAccounts)[0].PrincipalName + Write-AzOpsMessage -LogLevel Important -LogString 'New-AzOpsStateDeployment.EnrollmentAccount.First' -LogStringValues @($enrollmentAccounts)[0].PrincipalName $enrollmentAccountObjectId = @($enrollmentAccounts)[0].ObjectId } @@ -79,7 +79,7 @@ #endregion Subscription needs to be created #region Subscription exists already else { - Write-PSFMessage -Level Verbose -String 'New-AzOpsStateDeployment.Subscription.Exists' -StringValues $subscription.Name, $subscription.Id -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'New-AzOpsStateDeployment.Subscription.Exists' -LogStringValues $subscription.Name, $subscription.Id -Target $scopeObject Invoke-PSFProtectedCommand -ActionString 'New-AzOpsStateDeployment.Subscription.AssignManagementGroup' -ActionStringValues $subscription.Name, $scopeObject.ManagementGroupDisplayName -ScriptBlock { New-AzManagementGroupSubscription -GroupName $scopeObject.ManagementGroup -SubscriptionId $subscription.SubscriptionId -ErrorAction Stop } -Target $scopeObject -EnableException $true -PSCmdlet $PSCmdlet diff --git a/src/internal/functions/Register-AzOpsProviderFeature.ps1 b/src/internal/functions/Register-AzOpsProviderFeature.ps1 index 7317e88d..18b7df19 100644 --- a/src/internal/functions/Register-AzOpsProviderFeature.ps1 +++ b/src/internal/functions/Register-AzOpsProviderFeature.ps1 @@ -27,10 +27,10 @@ #TODO: Clarify original function design intent # Get Subscription ID from scope (since Subscription ID is not available for Resource Groups and Resources) - Write-PSFMessage -Level Verbose -String 'Register-AzOpsProviderFeature.Processing' -StringValues $ScopeObject, $FileName -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Register-AzOpsProviderFeature.Processing' -LogStringValues $ScopeObject, $FileName -Target $scopeObject $currentContext = Get-AzContext if ($ScopeObject.Subscription -and $currentContext.Subscription.Id -ne $ScopeObject.Subscription) { - Write-PSFMessage -Level Verbose -String 'Register-AzOpsProviderFeature.Context.Switching' -StringValues $currentContext.Subscription.Name, $CurrentAzContext.Subscription.Id, $ScopeObject.Subscription, $ScopeObject.Name -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Register-AzOpsProviderFeature.Context.Switching' -LogStringValues $currentContext.Subscription.Name, $CurrentAzContext.Subscription.Id, $ScopeObject.Subscription, $ScopeObject.Name -Target $scopeObject try { $null = Set-AzContext -SubscriptionId $ScopeObject.Subscription -ErrorAction Stop } @@ -43,7 +43,7 @@ $providerFeatures = Get-Content $FileName | ConvertFrom-Json foreach ($providerFeature in $providerFeatures) { if ($ProviderFeature.FeatureName -and $ProviderFeature.ProviderName) { - Write-PSFMessage -Level Verbose -String 'Register-AzOpsProviderFeature.Provider.Feature' -StringValues $ProviderFeature.FeatureName, $ProviderFeature.ProviderName -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Register-AzOpsProviderFeature.Provider.Feature' -LogStringValues $ProviderFeature.FeatureName, $ProviderFeature.ProviderName -Target $scopeObject Register-AzProviderFeature -Confirm:$false -ProviderNamespace $ProviderFeature.ProviderName -FeatureName $ProviderFeature.FeatureName } } diff --git a/src/internal/functions/Register-AzOpsResourceProvider.ps1 b/src/internal/functions/Register-AzOpsResourceProvider.ps1 index a11ae87b..d52cced4 100644 --- a/src/internal/functions/Register-AzOpsResourceProvider.ps1 +++ b/src/internal/functions/Register-AzOpsResourceProvider.ps1 @@ -25,10 +25,10 @@ ) process { - Write-PSFMessage -Level Verbose -String 'Register-AzOpsResourceProvider.Processing' -StringValues $ScopeObject, $FileName -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Register-AzOpsResourceProvider.Processing' -LogStringValues $ScopeObject, $FileName -Target $ScopeObject $currentContext = Get-AzContext if ($ScopeObject.Subscription -and $currentContext.Subscription.Id -ne $ScopeObject.Subscription) { - Write-PSFMessage -Level Verbose -String 'Register-AzOpsResourceProvider.Context.Switching' -StringValues $currentContext.Subscription.Name, $CurrentAzContext.Subscription.Id, $ScopeObject.Subscription, $ScopeObject.Name -Target $ScopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Register-AzOpsResourceProvider.Context.Switching' -LogStringValues $currentContext.Subscription.Name, $CurrentAzContext.Subscription.Id, $ScopeObject.Subscription, $ScopeObject.Name -Target $ScopeObject try { $null = Set-AzContext -SubscriptionId $ScopeObject.Subscription -ErrorAction Stop } @@ -42,8 +42,7 @@ foreach ($resourceprovider in $resourceproviders | Where-Object RegistrationState -eq 'Registered') { if (-not $resourceprovider.ProviderNamespace) { continue } - Write-PSFMessage -Level Important -String 'Register-AzOpsResourceProvider.Provider.Register' -StringValues $resourceprovider.ProviderNamespace - Write-AzOpsLog -Level Verbose -Topic "Register-AzOpsResourceProvider" -Message "Registering Provider $($resourceprovider.ProviderNamespace)" + Write-AzOpsMessage -LogLevel Important -LogString 'Register-AzOpsResourceProvider.Provider.Register' -LogStringValues $resourceprovider.ProviderNamespace Register-AzResourceProvider -Confirm:$false -Pre -ProviderNamespace $resourceprovider.ProviderNamespace } } diff --git a/src/internal/functions/Remove-AzOpsDeployment.ps1 b/src/internal/functions/Remove-AzOpsDeployment.ps1 index 67bc892b..1c144267 100644 --- a/src/internal/functions/Remove-AzOpsDeployment.ps1 +++ b/src/internal/functions/Remove-AzOpsDeployment.ps1 @@ -113,7 +113,7 @@ } } else { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.ResourceDependencyNested' -StringValues $roleAssignmentId, $policyAssignment.ResourceId + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.ResourceDependencyNested' -LogStringValues $roleAssignmentId, $policyAssignment.ResourceId } } } @@ -185,17 +185,17 @@ $fileItem = Get-Item -Path $TemplateFilePath $removeJobName = $fileItem.BaseName -replace '\.json$' -replace ' ', '_' $removeJobName = "AzOps-RemoveResource-$removeJobName" - Write-PSFMessage -Level Important -String 'Remove-AzOpsDeployment.Processing' -StringValues $removeJobName, $TemplateFilePath -Target $TemplateFilePath + Write-AzOpsMessage -LogLevel Important -LogString 'Remove-AzOpsDeployment.Processing' -LogStringValues $removeJobName, $TemplateFilePath #region Parse Content $templateContent = Get-Content $TemplateFilePath | ConvertFrom-Json -AsHashtable #endregion #region Validate it is AzOpsgenerated template $schemavalue = '$schema' if ($templateContent.metadata._generator.name -eq "AzOps" -or $templateContent.$schemavalue -like "*deploymentParameters.json#") { - Write-PSFMessage -Level Verbose -Message 'Remove-AzOpsDeployment.Metadata.Success' -StringValues $TemplateFilePath -Target $TemplateFilePath + Write-AzOpsMessage -LogLevel Verbose -LogString 'Remove-AzOpsDeployment.Metadata.Success' -LogStringValues $TemplateFilePath } else { - Write-PSFMessage -Level Error -Message 'Remove-AzOpsDeployment.Metadata.Failed' -StringValues $TemplateFilePath -Target $TemplateFilePath + Write-AzOpsMessage -LogLevel Error -LogString 'Remove-AzOpsDeployment.Metadata.Failed' -LogStringValues $TemplateFilePath return } #endregion Validate it is AzOpsgenerated template @@ -204,11 +204,11 @@ $scopeObject = New-AzOpsScope -Path $TemplateFilePath -StatePath $StatePath -ErrorAction Stop -WhatIf:$false } catch { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.Scope.Failed' -Target $TemplateFilePath -StringValues $TemplateFilePath -ErrorRecord $_ + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.Scope.Failed' -LogStringValues $TemplateFilePath -ErrorRecord $_ return } if (-not $scopeObject) { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.Scope.Empty' -Target $TemplateFilePath -StringValues $TemplateFilePath + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.Scope.Empty' -LogStringValues $TemplateFilePath return } #endregion Resolve Scope @@ -262,7 +262,7 @@ } # If no resource to delete was found return if (-not $resourceToDelete) { - Write-PSFMessage -Level Warning -String 'Remove-AzOpsDeployment.ResourceNotFound' -StringValues $scopeObject.Resource, $scopeObject.Scope -Target $scopeObject + Write-AzOpsMessage -LogLevel Warning -LogString 'Remove-AzOpsDeployment.ResourceNotFound' -LogStringValues $scopeObject.Resource, $scopeObject.Scope $results = 'What if operation failed:{1}Deletion of target resource {0}.{1}Resource could not be found' -f $scopeObject.scope, [environment]::NewLine Set-AzOpsWhatIfOutput -FilePath $TemplateFilePath -Results $results -RemoveAzOpsFlag $true return @@ -270,7 +270,7 @@ if ($dependency) { foreach ($resource in $dependency) { if ($resource.ResourceId -notin $deletionList.ScopeObject.Scope) { - Write-PSFMessage -Level Critical -String 'Remove-AzOpsDeployment.ResourceDependencyNotFound' -StringValues $resource.ResourceId, $scopeObject.Scope -Target $scopeObject + Write-AzOpsMessage -LogLevel Critical -LogString 'Remove-AzOpsDeployment.ResourceDependencyNotFound' -LogStringValues $resource.ResourceId, $scopeObject.Scope $results = 'Missing resource dependency:{2}{0} for successful deletion of {1}.{2}{2}Please add dependent resource to pull request and retry.' -f $resource.ResourceId, $scopeObject.scope, [environment]::NewLine Set-AzOpsWhatIfOutput -FilePath $TemplateFilePath -Results $results -RemoveAzOpsFlag $true $dependencyMissing = [PSCustomObject]@{ @@ -281,8 +281,8 @@ } else { $results = 'What if successful:{1}Performing the operation:{1}Deletion of target resource {0}.' -f $scopeObject.scope, [environment]::NewLine - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfResults' -StringValues $results -Target $scopeObject - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFile' -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Set-AzOpsWhatIfOutput.WhatIfResults' -LogStringValues $results + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFile' Set-AzOpsWhatIfOutput -FilePath $TemplateFilePath -Results $results -RemoveAzOpsFlag $true } if ($dependencyMissing) { @@ -290,15 +290,15 @@ } elseif ($dependency) { $results = 'What if successful:{1}Performing the operation:{1}Deletion of target resource {0}.' -f $scopeObject.scope, [environment]::NewLine - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfResults' -StringValues $results -Target $scopeObject - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFile' -Target $scopeObject + Write-AzOpsMessage -LogLevel Verbose -LogString 'Set-AzOpsWhatIfOutput.WhatIfResults' -LogStringValues $results + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFile' Set-AzOpsWhatIfOutput -FilePath $TemplateFilePath -Results $results -RemoveAzOpsFlag $true } if ($PSCmdlet.ShouldProcess("Remove $($scopeObject.Scope)?")) { $null = Remove-AzResource -ResourceId $scopeObject.Scope -Force } else { - Write-PSFMessage -Level Verbose -String 'Remove-AzOpsDeployment.SkipDueToWhatIf' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Remove-AzOpsDeployment.SkipDueToWhatIf' } } } diff --git a/src/internal/functions/Remove-AzOpsInvalidCharacter.ps1 b/src/internal/functions/Remove-AzOpsInvalidCharacter.ps1 index 501cc84c..1fc012d0 100644 --- a/src/internal/functions/Remove-AzOpsInvalidCharacter.ps1 +++ b/src/internal/functions/Remove-AzOpsInvalidCharacter.ps1 @@ -35,14 +35,14 @@ # Check if string contains invalid characters $pattern = $InvalidChars | Out-String -NoNewline if ($String -match "[$pattern]") { - Write-PSFMessage -Level Verbose -String 'Remove-AzOpsInvalidCharacter.Invalid' -StringValues $String -FunctionName 'Remove-AzOpsInvalidCharacter' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Remove-AzOpsInvalidCharacter.Invalid' -LogStringValues $String # Arrange string into character array $fileNameChar = $String.ToCharArray() # Iterate over each character in string foreach ($character in $fileNameChar) { # If character exists in invalid array then replace character if ($character -in $InvalidChars) { - Write-PSFMessage -Level Verbose -String 'Remove-AzOpsInvalidCharacter.Removal' -StringValues $character, $String -FunctionName 'Remove-AzOpsInvalidCharacter' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Remove-AzOpsInvalidCharacter.Removal' -LogStringValues $character, $String # Remove invalid character $String = $String.Replace($character.ToString(),'') } @@ -50,7 +50,7 @@ } # Always remove square brackets $String = $String -replace "(\[|\])","" - Write-PSFMessage -Level Verbose -String 'Remove-AzOpsInvalidCharacter.Completed' -StringValues $String -FunctionName 'Remove-AzOpsInvalidCharacter' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Remove-AzOpsInvalidCharacter.Completed' -LogStringValues $String # Return processed string return $String } diff --git a/src/internal/functions/Save-AzOpsManagementGroupChild.ps1 b/src/internal/functions/Save-AzOpsManagementGroupChild.ps1 index 7c7d3e63..bc005e0d 100644 --- a/src/internal/functions/Save-AzOpsManagementGroupChild.ps1 +++ b/src/internal/functions/Save-AzOpsManagementGroupChild.ps1 @@ -33,13 +33,13 @@ ) process { - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Starting' + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Starting' Invoke-PSFProtectedCommand -ActionString 'Save-AzOpsManagementGroupChild.Creating.Scope' -Target $Scope -ScriptBlock { $scopeObject = New-AzOpsScope -Scope $Scope -StatePath $StatePath -ErrorAction SilentlyContinue -Confirm:$false } -EnableException $true -PSCmdlet $PSCmdlet if (-not $scopeObject) { return } # In case -WhatIf is used - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Processing' -StringValues $scopeObject.Scope + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Processing' -LogStringValues $scopeObject.Scope # Construct all file paths for scope $scopeStatepath = $scopeObject.StatePath @@ -48,11 +48,11 @@ $statepathScopeDirectory = [IO.Directory]::GetParent($statepathDirectory).ToString() $statepathScopeDirectoryParent = [IO.Directory]::GetParent($statepathScopeDirectory).ToString() - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Data.StatePath' -StringValues $scopeStatepath - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Data.FileName' -StringValues $statepathFileName - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Data.Directory' -StringValues $statepathDirectory - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Data.ScopeDirectory' -StringValues $statepathScopeDirectory - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Data.ScopeDirectoryParent' -StringValues $statepathScopeDirectoryParent + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Data.StatePath' -LogStringValues $scopeStatepath + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Data.FileName' -LogStringValues $statepathFileName + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Data.Directory' -LogStringValues $statepathDirectory + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Data.ScopeDirectory' -LogStringValues $statepathScopeDirectory + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Data.ScopeDirectoryParent' -LogStringValues $statepathScopeDirectoryParent # If file is found anywhere in "AzOps.Core.State", ensure that it is at the right scope or else it doesn't matter if (Get-ChildItem -Path $Statepath -File -Recurse -Force | Where-Object Name -eq $statepathFileName) { @@ -63,9 +63,9 @@ if ( ((Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath') -notin '.') -and $exisitingScopePath.Parent.Parent.FullName -ne $statepathScopeDirectoryParent) { if ($exisitingScopePath.Parent.FullName -ne $statepathScopeDirectoryParent) { - Write-PSFMessage -Level Important -String 'Save-AzOpsManagementGroupChild.Moving.Source' -StringValues $exisitingScopePath + Write-AzOpsMessage -LogLevel Important -LogString 'Save-AzOpsManagementGroupChild.Moving.Source' -LogStringValues $exisitingScopePath Move-Item -Path $exisitingScopePath.Parent -Destination $statepathScopeDirectoryParent -Force - Write-PSFMessage -Level Important -String 'Save-AzOpsManagementGroupChild.Moving.Destination' -StringValues $statepathScopeDirectoryParent + Write-AzOpsMessage -LogLevel Important -LogString 'Save-AzOpsManagementGroupChild.Moving.Destination' -LogStringValues $statepathScopeDirectoryParent } } @@ -90,7 +90,7 @@ $subscriptions += Save-AzOpsManagementGroupChild -Scope $child.Id -StatePath $StatePath } else { - Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChild.Subscription.NotFound' -StringValues $child.Name + Write-AzOpsMessage -LogLevel Debug -LogString 'Save-AzOpsManagementGroupChild.Subscription.NotFound' -LogStringValues $child.Name } } else { @@ -138,6 +138,7 @@ ConvertTo-AzOpsState -Resource $subscription.Subscription -ExportPath $subscription.Path -StatePath $runspaceData.StatePath } } + Clear-PSFMessage } } } \ No newline at end of file diff --git a/src/internal/functions/Search-AzOpsAzGraph.ps1 b/src/internal/functions/Search-AzOpsAzGraph.ps1 index c257ae84..9a25f719 100644 --- a/src/internal/functions/Search-AzOpsAzGraph.ps1 +++ b/src/internal/functions/Search-AzOpsAzGraph.ps1 @@ -34,7 +34,7 @@ ) process { - Write-PSFMessage -Level Verbose -String 'Search-AzOpsAzGraph.Processing' -StringValues $Query + Write-AzOpsMessage -LogLevel Verbose -LogString 'Search-AzOpsAzGraph.Processing' -LogStringValues $Query $results = @() if ($UseTenantScope) { do { @@ -82,11 +82,11 @@ } } } - Write-PSFMessage -Level Verbose -String 'Search-AzOpsAzGraph.Processing.Done' -StringValues $Query + Write-AzOpsMessage -LogLevel Debug -LogString 'Search-AzOpsAzGraph.Processing.Done' -LogStringValues $Query return $resultsType } else { - Write-PSFMessage -Level Verbose -String 'Search-AzOpsAzGraph.Processing.NoResult' -StringValues $Query + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Search-AzOpsAzGraph.Processing.NoResult' -LogStringValues $Query } } diff --git a/src/internal/functions/Set-AzOpsContext.ps1 b/src/internal/functions/Set-AzOpsContext.ps1 index d8566fea..89af6256 100644 --- a/src/internal/functions/Set-AzOpsContext.ps1 +++ b/src/internal/functions/Set-AzOpsContext.ps1 @@ -25,7 +25,7 @@ process { if (-not $ScopeObject.Subscription) { return } if ($context.Subscription.Id -ne $ScopeObject.Subscription) { - Write-PSFMessage -Level Verbose -String 'Set-AzOpsContext.Change' -StringValues $context.Subscription.Name, $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsContext.Change' -LogStringValues $context.Subscription.Name, $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription Set-AzContext -SubscriptionId $scopeObject.Subscription -WhatIf:$false } } diff --git a/src/internal/functions/Set-AzOpsStringLength.ps1 b/src/internal/functions/Set-AzOpsStringLength.ps1 index 1d0b7e83..62d702c0 100644 --- a/src/internal/functions/Set-AzOpsStringLength.ps1 +++ b/src/internal/functions/Set-AzOpsStringLength.ps1 @@ -34,7 +34,7 @@ # Check if string exceed maximum length if (($String.Length + $buffer) -gt $MaxStringLength){ $overSize = $String.Length + $buffer - $MaxStringLength - Write-PSFMessage -Level Verbose -String 'Set-AzOpsStringLength.ToLong' -StringValues $String,$MaxStringLength,$overSize -FunctionName 'Set-AzOpsStringLength' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsStringLength.ToLong' -LogStringValues $String,$MaxStringLength,$overSize # Generate 64-character hash based on input string $stringStream = [IO.MemoryStream]::new([byte[]][char[]]$String) $stringHash = Get-FileHash -InputStream $stringStream -Algorithm SHA256 @@ -49,12 +49,12 @@ } # Construct new string with modified name $String = $String.Replace($String,$newName) - Write-PSFMessage -Level Verbose -String 'Set-AzOpsStringLength.Shortened' -StringValues $String,$MaxStringLength -FunctionName 'Set-AzOpsStringLength' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsStringLength.Shortened' -LogStringValues $String,$MaxStringLength return $String } else { # Return original string, it is within limit - Write-PSFMessage -Level Verbose -String 'Set-AzOpsStringLength.WithInLimit' -StringValues $String,$MaxStringLength -FunctionName 'Set-AzOpsStringLength' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsStringLength.WithInLimit' -LogStringValues $String,$MaxStringLength return $String } } diff --git a/src/internal/functions/Set-AzOpsWhatIfOutput.ps1 b/src/internal/functions/Set-AzOpsWhatIfOutput.ps1 index 73ca8c7c..45f481c3 100644 --- a/src/internal/functions/Set-AzOpsWhatIfOutput.ps1 +++ b/src/internal/functions/Set-AzOpsWhatIfOutput.ps1 @@ -47,7 +47,7 @@ process { $tempPath = [System.IO.Path]::GetTempPath() if ((-not (Test-Path -Path ($tempPath + 'OUTPUT.md'))) -or (-not (Test-Path -Path ($tempPath + 'OUTPUT.json')))) { - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFile' + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFile' New-Item -Path ($tempPath + 'OUTPUT.md') -WhatIf:$false | Out-Null New-Item -Path ($tempPath + 'OUTPUT.json') -WhatIf:$false | Out-Null } @@ -69,7 +69,7 @@ # Gather current OUTPUT.json content $existingContent = @(Get-Content -Path ($tempPath + 'OUTPUT.json') -Raw | ConvertFrom-Json -Depth 100) # Export results to json file - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFileAdding' -StringValues 'json', $FilePath, $ParameterFilePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFileAdding' -LogStringValues 'json', $FilePath, $ParameterFilePath if ($RemoveAzOpsFlag) { $resultJson = [PSCustomObject]@{ WhatIfResult = $Results @@ -85,7 +85,7 @@ Set-Content -Path ($tempPath + 'OUTPUT.json') -Value $existingContent -WhatIf:$false # Check if $existingContentStringMeasureMd and $resultStringMeasure exceed allowed size in $ResultSizeLimit if (($existingContentStringMeasureMd.Characters + $resultStringMeasure.Characters) -gt $ResultSizeLimit) { - Write-PSFMessage -Level Warning -String 'Set-AzOpsWhatIfOutput.WhatIfFileMax' -StringValues $ResultSizeLimit + Write-AzOpsMessage -LogLevel Warning -LogString 'Set-AzOpsWhatIfOutput.WhatIfFileMax' -LogStringValues $ResultSizeLimit $mdOutput = 'WhatIf Results for {1}:{0} WhatIf is too large for comment field, for more details look at PR files to determine changes.' -f [environment]::NewLine, $resultHeadline } else { @@ -105,11 +105,11 @@ } } if ((($mdOutput | Measure-Object -Line -Character -Word).Characters + $existingContentStringMeasureMd.Characters) -le $ResultSizeMaxLimit) { - Write-PSFMessage -Level Verbose -String 'Set-AzOpsWhatIfOutput.WhatIfFileAdding' -StringValues 'markdown', $FilePath, $ParameterFilePath + Write-AzOpsMessage -LogLevel InternalComment -LogString 'Set-AzOpsWhatIfOutput.WhatIfFileAdding' -LogStringValues 'markdown', $FilePath, $ParameterFilePath Add-Content -Path ($tempPath + 'OUTPUT.md') -Value $mdOutput -WhatIf:$false } else { - Write-PSFMessage -Level Warning -String 'Set-AzOpsWhatIfOutput.WhatIfMessageMax' -StringValues $ResultSizeMaxLimit + Write-AzOpsMessage -LogLevel Warning -LogString 'Set-AzOpsWhatIfOutput.WhatIfMessageMax' -LogStringValues $ResultSizeMaxLimit } } } \ No newline at end of file diff --git a/src/internal/functions/Write-AzOpsMessage.ps1 b/src/internal/functions/Write-AzOpsMessage.ps1 new file mode 100644 index 00000000..ccc15abc --- /dev/null +++ b/src/internal/functions/Write-AzOpsMessage.ps1 @@ -0,0 +1,192 @@ +function Write-AzOpsMessage { + <# + .SYNOPSIS + Wrapper function to emit logs with Write-PSFMessage and ApplicationInsights. + .PARAMETER ApplicationInsights + Boolean to indicate if function should emit logs to ApplicationInsights. + .PARAMETER Data + Additional data points. + .PARAMETER ErrorRecord + Additional exception information from catch. + .PARAMETER LogLevel + Set level of message severity. + .PARAMETER LogString + String used to construct message. + .PARAMETER LogStringValues + String array used to enrich to message. + .PARAMETER Metric + Used to output metric. + .PARAMETER MetricName + Override FunctionName as MetricName. + .PARAMETER FunctionName + Static set FunctionName in log, otherwise Write-AzOpsMessage collects this from callStack. + .PARAMETER ModuleName + Static set ModuleName in log, otherwise Write-AzOpsMessage collects this from callStack. + .PARAMETER Target + The object that was processed when invoked. + .EXAMPLE + Write-AzOpsMessage -LogLevel Verbose + #> + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $false)] + [bool] + $ApplicationInsights = (Get-PSFConfigValue -FullName 'AzOps.Core.ApplicationInsights'), + [Parameter(Mandatory = $false)] + [hashtable] + $Data, + [Parameter(Mandatory = $false)] + [System.Management.Automation.ErrorRecord] + $ErrorRecord, + [Parameter(Mandatory = $true)] + [ValidateSet("Critical", "Debug", "Error", "Host", "Important", "InternalComment", "Output", "Significant", "SomewhatVerbose", "System", "Verbose", "VeryVerbose", "Warning")] + [string] + $LogLevel, + [Parameter(Mandatory = $true)] + [string] + $LogString, + [Parameter(Mandatory = $false)] + [string[]] + $LogStringValues, + [Parameter(Mandatory = $false)] + [int] + $Metric, + [Parameter(Mandatory = $false)] + [string] + $MetricName, + [Parameter(Mandatory = $false)] + [string] + $FunctionName, + [Parameter(Mandatory = $false)] + [string] + $ModuleName, + [Parameter(Mandatory = $false)] + [string] + $Target + ) + begin { + # Collect callStack information to enrich logs with accurate caller information + $callStack = (Get-PSCallStack)[1] + if (-not $FunctionName) { $FunctionName = $callStack.Command } + if (-not $ModuleName) { $ModuleName = $callstack.InvocationInfo.MyCommand.ModuleName } + if (-not $ModuleName) { $ModuleName = "" } + $File = $callStack.Position.File + $Line = $callStack.Position.StartLineNumber + } + process { + # Evaluate message verbosity + $logLevels = @{ + "Critical" = 1 + "Debug" = 8 + "Error" = 667 + "Host" = 2 + "Important" = 2 + "InternalComment" = 9 + "Output" = 2 + "Significant" = 3 + "SomewhatVerbose" = 6 + "System" = 7 + "Verbose" = 5 + "VeryVerbose" = 4 + "Warning" = 666 + } + $intLevel = $logLevels[$LogLevel] + [int]$messageInfo = Get-PSFConfigValue -FullName 'PSFramework.Message.Info.Maximum' + if (($messageInfo -lt $intLevel) -or ([PSFramework.Message.MessageHost]::MinimumInformation -gt $intLevel) -and ($intLevel -notin 666..667)) { + # Message is below desired log verbosity, skip + return + } + # Generate unique logTag information, used to identify each log entry + $logTag = (New-Guid).Guid + '-' + (Get-Date).TimeOfDay.TotalMilliseconds + # Pass information to Write-PSFMessage, to emit local log + $params = @{ + Level = $LogLevel + String = $LogString + StringValues = $LogStringValues + Tag = $logTag + ModuleName = $ModuleName + FunctionName = $FunctionName + File = $File + Line = $Line + Target = $Target + ErrorRecord = $ErrorRecord + Data = $Data + } + Write-PSFMessage @params + if ($env:APPLICATIONINSIGHTS_CONNECTION_STRING -ne '' -and $ApplicationInsights -eq $true) { + # Initiate export of log to ApplicationInsights + try { + # Gather log generated by Write-PSFMessage with retry/backoff logic + $logMessage = Invoke-AzOpsScriptBlock -ArgumentList $FunctionName, $LogTag -ScriptBlock { + Get-PSFMessage -FunctionName $FunctionName | Where-Object { $_.Tags -eq $LogTag } -ErrorAction Stop + } -RetryCount 5 -RetryWait 1 -RetryType Exponential -ErrorAction Stop + } + catch { + Write-PSFMessage -Level Warning -Message 'Get-PSFMessage failing: {0}' -StringValues $_ + } + if (-not $logMessage) { + # No log message, return + return + } + if ($logMessage.Count -gt 1) { + # Log message has duplicate, return + Write-PSFMessage -Level Warning -Message 'Get-PSFMessage has duplicate entires for {0} with tag {1}' -StringValues $LogString, $logTag + return + } + # Construct ApplicationInsights object + $azOpsMessage = [Microsoft.ApplicationInsights.TelemetryClient]::new() + # Set ApplicationInsights connectionstring + $azOpsMessage.TelemetryConfiguration.ConnectionString = $env:APPLICATIONINSIGHTS_CONNECTIONSTRING + $azOpsMessage.Context.Session.Id = $PID + # Adjust logMessage.Level to align with ApplicationInsights + switch ($logMessage.Level) { + { ($_ -eq "SomewhatVerbose") -or ($_ -eq "System") -or ($_ -eq "Debug") -or ($_ -eq "InternalComment") } { + $level = "Verbose" + break + } + { ($_ -eq "Important") -or ($_ -eq "Output") -or ($_ -eq "Host") -or ($_ -eq "Significant") -or ($_ -eq "VeryVerbose") } { + $level = "Information" + break + } + default { + $level = ($logMessage.Level).ToString() + break + } + } + # Create ApplicationInsights customDimensions + $logProperties = [System.Collections.Generic.Dictionary[string, string]]::new() + $logProperties.Add("Timestamp", $logMessage.Timestamp) + $logProperties.Add("ModuleName", $logMessage.ModuleName) + $logProperties.Add("FunctionName", $logMessage.FunctionName) + $logProperties.Add("TargetObject", $logMessage.TargetObject) + $logProperties.Add("Data", $logmessage.Data) + $logProperties.Add("Runspace", $logMessage.Runspace) + $logProperties.Add("ComputerName", $logMessage.ComputerName) + $logProperties.Add("File", $logMessage.File) + $logProperties.Add("Line", $logMessage.Line) + $logProperties.Add("CallStack", $logMessage.CallStack) + $logProperties.Add("ErrorRecord", $logMessage.ErrorRecord) + $logProperties.Add("String", $logMessage.String) + # Create TrackTrace + $azOpsMessage.TrackTrace($logMessage.Message, $level, $logProperties) + # Create TrackEvent + $azOpsMessage.TrackEvent($logMessage.FunctionName) + if ($Metric) { + # Create TrackMetric + if (-not $MetricName) { + $azOpsMessage.TrackMetric($logMessage.FunctionName, $Metric) + } + else { + $azOpsMessage.TrackMetric($MetricName, $Metric) + } + } + if ($level -eq "Critical" -or $level -eq "Error" -or $level -eq "Warning") { + # Create TrackException + $azOpsMessage.TrackException($logMessage.Message, $logProperties) + } + # Immediately emit log to ApplicationInsights + $azOpsMessage.Flush() + } + } +} \ No newline at end of file diff --git a/src/localized/en-us/Strings.psd1 b/src/localized/en-us/Strings.psd1 index feb30461..4f93a81b 100644 --- a/src/localized/en-us/Strings.psd1 +++ b/src/localized/en-us/Strings.psd1 @@ -96,8 +96,10 @@ 'Get-AzOpsPolicyExemption.ManagementGroup' = 'Retrieving Policy Exemption for Management Group {0} ({1})' # $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup 'Get-AzOpsPolicyExemption.ResourceGroup' = 'Retrieving Policy Exemption for Resource Group {0}' # $ScopeObject.ResourceGroup 'Get-AzOpsPolicyExemption.Subscription' = 'Retrieving Policy Exemption for Subscription {0} ({1})' # $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription + 'Get-AzOpsPolicyExemption.Failed' = 'Retrieving Policy Exemption failed at {0}' # $ScopeObject.Scope 'Get-AzOpsResourceLock.ResourceGroup' = 'Retrieving Resource Locks for Resource Group {0}' # $ScopeObject.ResourceGroup + 'Get-AzOpsResourceLock.Failed' = 'Failed retrieving Resource Locks {0}' # $_ 'Get-AzOpsResourceLock.Subscription' = 'Retrieving Resource Locks for Subscription {0} ({1})' # $ScopeObject.SubscriptionDisplayName, $ScopeObject.Subscription 'Get-AzOpsPolicySetDefinition.ManagementGroup' = 'Retrieving PolicySet Definition for ManagementGroup {0} ({1})' # $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup @@ -117,14 +119,16 @@ 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery.NotFound' = 'No resources found in [{0}]' # $scopeObject.Name 'Get-AzOpsResourceDefinition.Processing.Resource.Warning' = 'Failed to get resources in {0}]. Consider excluding the resource causing the failure with [Core.SkipResourceType] setting' # $scopeObject.Name 'Get-AzOpsResourceDefinition.SkippingResourceGroup' = 'SkipResourceGroup switch used, skipping resource Group discovery' # - 'Get-AzOpsResourceDefinition.SkippingResources' = 'Resources are skipped in due to SkipResource.' # + 'Get-AzOpsResourceDefinition.SkippingResources' = 'SkipResource switch used, skipping resource discovery.' # 'Get-AzOpsResourceDefinition.Processing.ChildResource' = 'Processing resource [{0}] in resource Group [{1}]' # $resource.Name, $resourceGroup.ResourceGroupName - 'Get-AzOpsResourceDefinition.SkippingChildResources' = 'Child resources are skipped, due to SkipChildResource' # + 'Get-AzOpsResourceDefinition.SkippingChildResources' = 'SkipChildResource switch used, skipping child resource discovery' # 'Get-AzOpsRoleAssignment.Assignment' = 'Found assignment {0} for role {1}' # $roleAssignment.id, $roleAssignment.properties.roleDefinitionId + 'Get-AzOpsRoleAssignment.Processing.Failed' = 'Failed retrieving roleAssignment {0}' # $_ 'Get-AzOpsRoleAssignment.Processing' = 'Retrieving Role Assignments at scope {0}' # $ScopeObject 'Get-AzOpsRoleDefinition.Processing' = 'Processing scope {0}' # $ScopeObject + 'Get-AzOpsRoleDefinition.Processing.Failed' = 'Failed retrieving roleDefinition {0}' # $_ 'Get-AzOpsRoleDefinition.Definition' = 'Processing object {0}' # $roleDefinition.id 'Get-AzOpsRoleEligibilityScheduleRequest.Processing' = 'Retrieving Privileged Identity Management RoleEligibilitySchedule at [{0}]' # $ScopeObject.Scope @@ -176,6 +180,7 @@ 'Invoke-AzOpsPull.Validating.UserRole.Failed' = 'Insufficient access to Azure AD. Privileged Identity Management information will not be pulled' # 'Invoke-AzOpsPull.Validating.UserRole.Success' = 'Azure access validated' # 'Invoke-AzOpsPull.Validating.ResourceGroupDiscovery.Failed' = 'SkipResource set to false or SkipChildResource set to false requires SkipResourceGroup to be set to false. Change value for SkipResourceGroup and retry operation. {0} https://github.com/azure/azops/wiki/settings' # + 'Invoke-AzOpsPull.SkipResourceType.Failed' = 'SkipResourceType setting conflict found in IncludeResourceType, ignoring {0} from IncludeResourceType. To avoid this remove {0} from IncludeResourceType or SkipResourceType' # $resourceTypeDiff.InputObject 'Invoke-AzOpsRestMethod.Processing' = 'Invoke-AzRestMethod processing path: [{0}]' # $Path 'Invoke-AzOpsRestMethod.Processing.Error' = 'Invoke-AzRestMethod received [{0}] while processing: [{1}]' # $_, $Path @@ -196,6 +201,7 @@ 'Invoke-AzOpsPush.Deployment.ParallelGroup' = 'Identified multiple deployments with matching TemplateFilePath' # $groups 'Invoke-AzOpsPush.Dependency.Missing' = 'Missing resource dependency for successfull deletion. Error exiting runtime.' 'Invoke-AzOpsPush.DeploymentList.NotFound' = 'Expecting deploymentList object, it was not found. Error exiting runtime.' + 'Invoke-AzOpsPush.Duration' = 'AzOps Push completed in {0}' # $stopWatch.Elapsed 'Invoke-AzOpsPush.Resolve.FoundTemplate' = 'Found template {1} for parameters {0}' # $FilePath, $templatePath 'Invoke-AzOpsPush.Resolve.FoundBicepTemplate' = 'Found Bicep template {1} for parameters {0}' # $FilePath, $bicepTemplatePath 'Invoke-AzOpsPush.Resolve.FromMainTemplate' = 'Determining template from main template file: {0}' # $mainTemplateItem.FullName @@ -209,11 +215,12 @@ 'Invoke-AzOpsPush.Resolve.NotFoundParamFileDefaultValue' = 'Template {0} with parameter: {1} missing defaultValue and no parameter file found, skip deployment' # $FilePath, $missingString 'Invoke-AzOpsPush.Scope.Failed' = 'Failed to read {0} as part of {1}' # $addition, $StatePath + 'Invoke-AzOpsNativeCommand' = 'Execution of ScriptBlock: {{{0}}} returned: {{{1}}}' # $ScriptBlock, $_ 'Invoke-AzOpsNativeCommand.Failed.NoCallstack' = 'Execution of {{{0}}} failed with exit code {1}' # $ScriptBlock, $LASTEXITCODE 'Invoke-AzOpsNativeCommand.Failed.WithCallstack' = 'Execution of {{{0}}} by {1}: line {2} failed with exit code {3}' # $ScriptBlock, $caller[1].ScriptName, $caller[1].ScriptLineNumber, $LASTEXITCODE - 'Invoke-AzOpsScriptBlock.Failed.GivingUp' = 'Tried unsuccessfully {0} out of {1} times, giving up.' # $count, $RetryCount - 'Invoke-AzOpsScriptBlock.Failed.WillRetry' = 'Tried unsuccessfully {0} out of {1} times, keeping up the fight!' # $count, $RetryCount + 'Invoke-AzOpsScriptBlock.Failed.GivingUp' = 'Tried {0} unsuccessfully {1} out of {2} times, giving up.' # $ScriptBlock, $count, $RetryCount + 'Invoke-AzOpsScriptBlock.Failed.WillRetry' = 'Tried {0} unsuccessfully {1} out of {2} times, keeping up the fight!' # $ScriptBlock, $count, $RetryCount 'New-AzOpsScope.Creating.FromFile' = 'Creating new scope from path {0}' # $Path 'New-AzOpsScope.Creating.FromScope' = 'Creating new AzOpsScope object using scope [{0}]' # $Scope