diff --git a/src/ContainerInstance/UX/Microsoft.ContainerInstance/containerGroups.json b/src/ContainerInstance/UX/Microsoft.ContainerInstance/containerGroups.json index 249fa6a2d7c8..fec62ac0a192 100644 --- a/src/ContainerInstance/UX/Microsoft.ContainerInstance/containerGroups.json +++ b/src/ContainerInstance/UX/Microsoft.ContainerInstance/containerGroups.json @@ -35,6 +35,10 @@ { "name":"-ResourceGroupName", "value":"[path.resourceGroupName]" + }, + { + "name":"-Name", + "value":"[path.containerGroupName]" } ] } diff --git a/src/CosmosDB/CosmosDB/UX/Microsoft.CosmosDB/databaseAccounts.json b/src/CosmosDB/CosmosDB/UX/Microsoft.DocumentDB/databaseAccounts.json similarity index 100% rename from src/CosmosDB/CosmosDB/UX/Microsoft.CosmosDB/databaseAccounts.json rename to src/CosmosDB/CosmosDB/UX/Microsoft.DocumentDB/databaseAccounts.json diff --git a/tools/ExecuteCIStep.ps1 b/tools/ExecuteCIStep.ps1 index 1cf1024bea36..05491e19b904 100644 --- a/tools/ExecuteCIStep.ps1 +++ b/tools/ExecuteCIStep.ps1 @@ -326,7 +326,6 @@ If ($StaticAnalysisUX) If ("" -Ne $UXModuleList) { Write-Host "Running static analysis for UX metadata..." - .("$PSScriptRoot/StaticAnalysis/UXMetadataAnalyzer/PrepareUXMetadata.ps1") -RepoArtifacts $RepoArtifacts -Configuration $Configuration dotnet $RepoArtifacts/StaticAnalysis/StaticAnalysis.Netcore.dll -p $RepoArtifacts/$Configuration -r $StaticAnalysisOutputDirectory --analyzers ux -u -m $UXModuleList } Return diff --git a/tools/StaticAnalysis/Exceptions/Az.Compute/UXMetadataIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Compute/UXMetadataIssues.csv new file mode 100644 index 000000000000..08f8157cccdd --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.Compute/UXMetadataIssues.csv @@ -0,0 +1,2 @@ +"Module","Severity","ResourceType","SubResourceType","Command","Description" +"Az.Compute","1","Microsoft.Compute","virtualMachineScaleSets","Stop-AzVmss","The value of -StayProvisioned is not defined." diff --git a/tools/StaticAnalysis/Exceptions/Az.KeyVault/UXMetadataIssues.csv b/tools/StaticAnalysis/Exceptions/Az.KeyVault/UXMetadataIssues.csv new file mode 100644 index 000000000000..575d65200044 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.KeyVault/UXMetadataIssues.csv @@ -0,0 +1,4 @@ +"Module","Severity","ResourceType","SubResourceType","Command","Description" +"Az.KeyVault","1","Microsoft.KeyVault","vaults","Get-AzKeyVaultKey","resourceGroupName is defined in path but cannot find in example" +"Az.KeyVault","1","Microsoft.KeyVault","vaults","Get-AzKeyVaultCertificate","resourceGroupName is defined in path but cannot find in example" +"Az.KeyVault","1","Microsoft.KeyVault","vaults","Get-AzKeyVaultSecret","resourceGroupName is defined in path but cannot find in example" diff --git a/tools/StaticAnalysis/Exceptions/Az.RedisEnterpriseCache/UXMetadataIssues.csv b/tools/StaticAnalysis/Exceptions/Az.RedisEnterpriseCache/UXMetadataIssues.csv new file mode 100644 index 000000000000..a9f7019c37cd --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.RedisEnterpriseCache/UXMetadataIssues.csv @@ -0,0 +1,3 @@ +"Module","Severity","ResourceType","SubResourceType","Command","Description" +"Az.RedisEnterpriseCache","1","Microsoft.Cache","redisEnterprise-databases","Invoke-AzRedisEnterpriseCacheForceDatabaseUnlink","Cannot find a matched parameter set for example of Invoke-AzRedisEnterpriseCacheForceDatabaseUnlink" +"Az.RedisEnterpriseCache","1","Microsoft.Cache","redisEnterprise-databases","Invoke-AzRedisEnterpriseCacheForceDatabaseUnlink","databaseName is defined in path but cannot find in example" diff --git a/tools/StaticAnalysis/UXMetadataAnalyzer/PrepareUXMetadata.ps1 b/tools/StaticAnalysis/UXMetadataAnalyzer/PrepareUXMetadata.ps1 deleted file mode 100644 index a68598904524..000000000000 --- a/tools/StaticAnalysis/UXMetadataAnalyzer/PrepareUXMetadata.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -# ---------------------------------------------------------------------------------- -# Copyright Microsoft Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ---------------------------------------------------------------------------------- - -# Move the UX metadata files under modules to the artifacts folder for veridation. Merge the metadata file if the module is hybrid and both have metadata for the same sub resource type. - -Param( - [String] - $RepoArtifacts='artifacts', - - [String] - $Configuration='Debug' -) - -$ConfigurationFolderPath = "$RepoArtifacts/$Configuration" -$Modules = Get-ChildItem -Path $ConfigurationFolderPath | % { $_.BaseName } -Write-Host $Modules -ForEach ($ModuleName In $Modules) -{ - $RPName = $ModuleName.Replace("Az.", "") - $SourceFolder = "$PSScriptRoot/../../../src/$RPName" - $UXFolderPath = "$ConfigurationFolderPath/$ModuleName/UX" - $MetadataFileArray = Get-ChildItem -Path $SourceFolder -Recurse -Filter UX | Get-ChildItem -Recurse -Filter *.json | % { $_.FullName } - If ($MetadataFileArray.Length -Eq 0) - { - Continue - } - - If (-Not (Test-Path -Path $UXFolderPath)) - { - New-Item -ItemType Directory -Path $UXFolderPath - } - ForEach ($MetadataFile In $MetadataFileArray) - { - $ResourceType = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName($MetadataFile)) - $ResourceTypeFolder = "$UXFolderPath/$ResourceType" - If (-Not (Test-Path -Path $ResourceTypeFolder)) - { - New-Item -ItemType Directory -Path $ResourceTypeFolder - } - $FileName = [System.IO.Path]::GetFileName($MetadataFile) - $TargetPath = "$ResourceTypeFolder/$FileName" - If (-Not (Test-Path -Path $TargetPath)) - { - Copy-Item -Path $MetadataFile -Destination $TargetPath - } - Else - { - #Merge the json files for the same sub resource type in hybrid module - $Metadata1 = Get-Content -Path $TargetPath | ConvertFrom-Json - $Metadata2 = Get-Content -Path $MetadataFile | ConvertFrom-Json - $Metadata1.commands += $Metadata2.commands - - ConvertTo-Json -Depth 10 -InputObject $Metadata1 | Out-File -FilePath $TargetPath - } - } -} diff --git a/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataAnalyzer.cs b/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataAnalyzer.cs index a96fe5597960..5b2a8371d0b3 100644 --- a/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataAnalyzer.cs +++ b/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataAnalyzer.cs @@ -111,21 +111,19 @@ public void Analyze( continue; } string moduleName = Path.GetFileName(directory); - + string moduleFolder = Path.Combine(savedDirectory, "src", moduleName.Replace("Az.", "")); Directory.SetCurrentDirectory(directory); var moduleMetadata = MetadataLoader.GetModuleMetadata(moduleName); - string UXFolder = Path.Combine(directory, "UX"); - if (!Directory.Exists(UXFolder)) - { - continue; - } - - var UXMetadataPathList = Directory.EnumerateFiles(UXFolder, "*.json", SearchOption.AllDirectories); - foreach (var UXMetadataPath in UXMetadataPathList) + string[] UXFolders = Directory.GetDirectories(moduleFolder, "UX", SearchOption.AllDirectories); + foreach (var UXFolder in UXFolders) { - ValidateUXMetadata(moduleName, UXMetadataPath, moduleMetadata, issueLogger); + var UXMetadataPathList = Directory.EnumerateFiles(UXFolder, "*.json", SearchOption.AllDirectories); + foreach (var UXMetadataPath in UXMetadataPathList) + { + ValidateUXMetadata(moduleName, UXMetadataPath, moduleMetadata, issueLogger); + } } Directory.SetCurrentDirectory(savedDirectory); } @@ -261,8 +259,15 @@ private void ValidateParametersDefinedInPathContainsInExample(IssueLoggerContext private void ValidateParametersInExampleDefinedInPath(IssueLoggerContext context, HashSet parametersFromHttpPath, UXMetadataCommandExample example, ReportLogger issueLogger) { var exampleParameterPathRegex = new Regex(@"path\.([\w]+)"); - foreach (string parameterInExample in example.Parameters.Select(x => x.Value)) + foreach (var parameter in example.Parameters) { + string parameterInExample = parameter.Value; + if (parameterInExample == null) + { + string description = string.Format("The value of {0} is not defined.", parameter.Name); + issueLogger.LogUXMetadataIssue(context, 1, description); + continue; + } var match = exampleParameterPathRegex.Match(parameterInExample); if (!match.Success) { diff --git a/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataIssue.cs b/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataIssue.cs index dd01d66667b2..e5039bc091d3 100644 --- a/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataIssue.cs +++ b/tools/StaticAnalysis/UXMetadataAnalyzer/UXMetadataIssue.cs @@ -58,7 +58,7 @@ public bool Match(IReportRecord other) public IReportRecord Parse(string line) { - var matcher = "\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\""; + var matcher = "\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]*)\",\"([^\"]+)\""; var match = Regex.Match(line, matcher); if (!match.Success || match.Groups.Count < 7) {