diff --git a/build.proj b/build.proj index 577bccc4e83d..39e5456ec2c2 100644 --- a/build.proj +++ b/build.proj @@ -60,6 +60,7 @@ Condition=" '$(Scope)' == 'ServiceManagement'"/> + @@ -138,7 +139,7 @@ $(MSBuildProjectDirectory)\restore.config -ConfigFile "$(NuGetRestoreConfigFile)" -PackagesDirectory $(LibraryNugetPackageFolder) - + -PackagesDirectory ".\experiments\Websites.Experiments\packages" C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe @@ -169,7 +170,10 @@ - + + @@ -191,7 +195,14 @@ Targets="Build" Properties="Configuration=$(Configuration);Platform=Any CPU" BuildInParallel="$(BuildInParallel)" - ContinueOnError="false" /> + ContinueOnError="false" /> + + + DestinationFolder="$(LibrarySourceFolder)\Package\$(Configuration)" Condition= " '$(NetCore)' == 'false' "/> + @@ -453,6 +465,9 @@ + + diff --git a/experiments/Websites.Experiments/AzureRM.Websites.Experiments.Tests.ps1 b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.Tests.ps1 new file mode 100644 index 000000000000..a2d3a1626683 --- /dev/null +++ b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.Tests.ps1 @@ -0,0 +1,1176 @@ +# ---------------------------------------------------------------------------------- +# +# 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. +# ---------------------------------------------------------------------------------- + + +InModuleScope AzureRM.Websites.Experiments { + + function Get-AzureRmAppServicePlanMock { + param( + [string]$PlanName, + [string]$GroupName, + [object[]]$Plans + ) + if ($PlanName -and $GroupName){ + return @{Id=$PlanName;Name=$PlanName;ResourceGroup=$GroupName} + } else { + return $Plans + } + } + + function Get-AzureRmResourceGroupMock { + param( + [string]$Name, + [object[]]$Groups + ) + + return $Groups | Where-Object {$_.ResourceGroupName -eq $Name} + } + + Describe "Get-WebAppName "{ + $randomNumber = 1 + $defaultName = "WebApp$randomNumber" + Context "[mock] When name is not provided: " { + Mock Get-Random {return $randomNumber} + Mock Test-NameAvailability {return $true} + + $result = Get-WebAppName -ProvidedParameters @{} + + It "Returns string with defaultName" { + $result | Should BeOfType System.String + $result | Should Be $defaultName + } + } + + Context "[mock] When name is provided and + name is available: " { + $customName = "customName" + Mock Test-NameAvailability {return $true} + + $result = Get-WebAppName -ProvidedParameters @{WebAppName=$customName} + + It "Returns a string with provided name" { + $result | Should BeOfType System.String + $result | Should Be $customName + } + } + + Context "[mock] When name is provided and + name is NOT available: " { + $customName = "customName" + Mock Test-NameAvailability {return $false} + + It "Should throw." { + {$result = Get-WebAppName -ProvidedParameters @{WebAppName=$customName}} | Should Throw + } + } + } + + Describe "Get-ResourceGroupInfo "{ + $webAppName = "MyWebAppName1" + Context "[mock] When a ResourceGroupName is not provided and + WebAppName is not equal to an existing resource group: " { + Mock Test-ResourceGroupExistence {return $false} + + $result = Get-ResourceGroupInfo ` + -ProvidedParameters @{} ` + -WebAppName $webAppName + + It "Returns a hashtable." { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same value as webAppName." { + $result.Name| Should Be $webAppName + } + + It "Returns a hashtable with key 'Exists' set to 'False'." { + $result.Exists | Should Be $false + } + } + + Context "[mock] When a ResourceGroupName is not provided and + WebAppName is equal to an existing resource group: " { + Mock Test-ResourceGroupExistence {return $true} + + $result = Get-ResourceGroupInfo ` + -ProvidedParameters @{} ` + -WebAppName $webAppName + + It "Returns a hashtable." { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same value as webAppName." { + $result.Name| Should Be $webAppName + } + + It "Returns a hashtable with key 'Exists' set to 'False'." { + $result.Exists | Should Be $true + } + } + + Context "[mock] When a ResourceGroupName is provided and + that name does not already exist: " { + $customName = "customName" + Mock Test-ResourceGroupExistence {return $false} + + $result = Get-ResourceGroupInfo ` + -ProvidedParameters @{ResourceGroupName=$customName} ` + -WebAppName $webAppName + + It "Returns a hashtable." { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same value as provided name." { + $result.Name| Should Be $customName + } + + It "Returns a hashtable with key 'Exists' set to 'False'." { + $result.Exists | Should Be $false + } + } + + Context "[mock] When a ResourceGroupName is provided and + that name already exists: " { + $customName = "customName" + Mock Test-ResourceGroupExistence {return $true} + + $result = Get-ResourceGroupInfo ` + -ProvidedParameters @{ResourceGroupName=$customName} ` + -WebAppName $webAppName + + It "Returns a hashtable." { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same value as provided name." { + $result.Name| Should Be $customName + } + + It "Returns a hashtable with key 'Exists' set to 'True'." { + $result.Exists | Should Be $true + } + } + } + + + Describe "Get-AppServicePlanInfo" { + $webAppName = "MyWebAppName1" + Context "When no parameters are provided and + there is not a default app service plan: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $groupName = "group1" + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same value as the WebAppName. " { + $result.Name | Should Be $webAppName + } + + It "Returns a hashtable with key 'Exists' set to 'False'. " { + $result.Exists | Should Be $false + } + + It "Returns a hashtable with key 'ResourceGroup' set to ResourceGroupName passed. " { + $result.ResourceGroup | Should Be $groupName + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $false + } + } + + Context "When no parameters are provided and + there is a default app service plan: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + $groupName = "group1" + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same vaue as the first plan with default characteristics. " { + $result.Name | Should Be $plan2.Name + } + + It "Returns a hashtable with key 'Exists' set 'True'. " { + $result.Exists | Should Be $true + } + + It "Returns a hashtable with key 'ResourceGroup' set to same value as the first default plan's resource group. " { + $result.ResourceGroup | Should Be $plan2.ResourceGroup + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $true + } + } + + Context "When an Id is provided and + plan name exists and + group provided matches the provided in the id: " { + $planName = "plan1" + $groupName = "group1" + $planId = "/subscriptions/f30a7701-df2c-4bc7-ba8d-ab11861ca13c/resourceGroups/$groupName/providers/Microsoft.Web/serverfarms/$planName" + $plan1 = @{Id=$planId;Name=$planName;Sku=@{Tier="Basic"};ResourceGroup=$groupName} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$planId} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same vaue as the plan wiht matching ID. " { + $result.Name | Should Be $planName + } + + It "Returns a hashtable with key 'Exists' set 'True'. " { + $result.Exists | Should Be $true + } + + It "Returns a hashtable with key 'ResourceGroup' set to same resource group found in the ID. " { + $result.ResourceGroup | Should Be $groupName + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $false + } + } + + Context "When an Id is provided and + the Id does not belong to any existent plan: " { + $planName = "plan1" + $groupName = "group1" + $planId = "/subscriptions/f30a7701-df2c-4bc7-ba8d-ab11861ca13c/resourceGroups/$groupName/providers/Microsoft.Web/serverfarms/$planName" + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan2,$plan3) + Mock Get-AzureRmAppServicePlan {return $plans} + + It "Should throw. " { + { + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$planId} ` + -WebAppName $webAppName ` + -ResourceGroupName $nonMatchingGroupName + } | Should Throw + } + } + + Context "When a plan name is provided and + the plan name does not exist: " { + $planName = "customName" + $groupName = "customGroup" + $plan1 = @{Id="plan1Id";Name="plan1";Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$planName} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same name provided. " { + $result.Name | Should Be $planName + } + + It "Returns a hashtable with key 'Exists' set 'False'. " { + $result.Exists | Should Be $false + } + + It "Returns a hashtable with key 'ResourceGroup' set to ResourceGroupName passed. " { + $result.ResourceGroup | Should Be $groupName + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $false + } + } + + Context "When a plan name is provided and + plan name exists and + there are various plans with the same name and + a Resource Group matching ResourceGroupName passed contains that plan name : " { + $existingPlanName = "existingPlan" + $groupName = "existingGroup" + $plan1 = @{Id="plan1Id";Name=$existingPlanName;Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name=$existingPlanName;Sku=@{Tier="Free"};ResourceGroup=$groupName} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$existingPlanName} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same name provided. " { + $result.Name | Should Be $existingPlanName + } + + It "Returns a hashtable with key 'Exists' set to 'True'. " { + $result.Exists | Should Be $true + } + + It "Returns a hashtable with key 'ResourceGroup' set to passed ResourceGroupName. " { + $result.ResourceGroup | Should Be $groupName + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $false + } + } + + Context "When a plan name is provided and + plan name exists and + there are various plans with the same name and + a there is not Resource Group matching ResourceGroupName passed which contains that plan name : " { + $existingPlanName = "customPlan" + $groupName = "customGroup" + $plan1 = @{Id="plan1Id";Name=$existingPlanName;Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name=$existingPlanName;Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + Mock Get-AzureRmAppServicePlan {return $plans} + + It "Should Throw. " { + { + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$existingPlanName} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + } | Should Throw + } + } + + Context "When a plan name is provided and + plan name exists and + there is one with that same name and + a there is not Resource Group matching ResourceGroupName passed which contains that plan name : " { + $existingPlanName = "customPlan" + $existingPlanGroup = "customGroup" + $groupName = "passedGroup" + $plan1 = @{Id="plan1Id";Name=$existingPlanName;Sku=@{Tier="Free"};ResourceGroup=$existingPlanGroup} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="plan3Id";Name="plan3";Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + Mock Get-AzureRmAppServicePlan {return $plans} + + $result = Get-AppServicePlanInfo ` + -ProvidedParameters @{AppServicePlan=$existingPlanName} ` + -WebAppName $webAppName ` + -ResourceGroupName $groupName + + It "Returns a hashtable. " { + $result | Should BeOfType System.Collections.Hashtable + } + + It "Returns a hashtable with key 'Name' set to same name provided. " { + $result.Name | Should Be $existingPlanName + } + + It "Returns a hashtable with key 'Exists' set to 'True'. " { + $result.Exists | Should Be $true + } + + It "Returns a hashtable with key 'ResourceGroup' set to passed ResourceGroupName. " { + $result.ResourceGroup | Should Be $existingPlanGroup + } + + It "Returns a hashtable with key 'IsDefaultPlan' set to 'False'. " { + $result.IsDefaultPlan | Should Be $false + } + + } + } + + Describe "Get-Location" { + $defaultLocation = "West Europe" + Mock Get-DefaultLocation {return $defaultLocation} + Context "When a location is not provided and + ResourceGroupName passed does not exist."{ + $groupName = "customGroup" + $resourceGroupExists = $false + + $result = Get-Location -ProvidedParameters @{} -ResourceGroupName $groupName -ResourceGroupExists $resourceGroupExists + + It "Returns a string with default location. " { + $result | Should BeOfType System.String + $result | Should Be $defaultLocation + } + } + + Context "When a location is not provided and + ResourceGroupName passed exists."{ + $groupName = "customGroup" + $groupLocation = "customGroupLocation" + $group1 = @{ResourceGroupName=$groupName;Location=$groupLocation} + $group2 = @{ResourceGroupName="group2";Location="loc2"} + $groups = @($group1,$group2) + $resourceGroupExists = $true + Mock Get-AzureRmResourceGroup {return $groups | Where-Object {$_.ResourceGroupName -eq $Name}} + + $result = Get-Location -ProvidedParameters @{} -ResourceGroupName $groupName -ResourceGroupExists $resourceGroupExists + + It "Returns a string with default location. " { + $result | Should BeOfType System.String + $result | Should Be $groupLocation + } + } + + Context "When a location is provided."{ + $providedLocation = "customLocation" + + $result = Get-Location -ProvidedParameters @{Location=$providedLocation} + + It "Returns a string with the provided location. " { + $result | Should BeOfType System.String + $result | Should Be $providedLocation + } + } + } + + Describe "New-AzWebAppJustDoIt"{ + $randomNumber = 1 + $defaultName = "WebApp$randomNumber" + $defaultLocation = "West Europe" + Mock Get-Random {return $randomNumber} + Mock Get-DefaultLocation {return $defaultLocation} + $validLocations = @("loc1","loc2","loc3") + Mock Get-AzureRmResourceProvider{return @(@{ProviderNamespace="Microsoft.Web";Locations=$validLocations})} + Mock Get-Context {} + Mock Get-WebSitesClient {} + Mock Get-ResourceManagementClient {} + Context "[mock] When no parameters are provided and + there is not default plan: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with a NEW ResourceGroup with same name as the webapp." { + $result.ResourceGroupName | Should be $defaultName + $result.ResourceGroupName | Should be $result.Name + } + + It "Returns Site with default location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with a NEW AppServicePlan with same name as the webapp." { + $result.AppServicePlan | Should be $defaultName + $result.AppServicePlan | Should be $result.Name + } + } + + Context "[mock] When name is provided and + there is not default plan: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2Id";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $customName = "customName" + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $appPlans} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -WebAppName $customName + + It "Returns Site with provided name." { + $result.Name | Should be $customName + } + + It "Returns Site with a NEW ResourceGroup with same name as the webapp." { + $result.ResourceGroupName | Should be $customName + } + + It "Returns Site with default location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with a NEW AppServicePlan with same name as the webapp." { + $result.AppServicePlan | Should be $customName + } + } + + Context "[mock] When no parameters are provided and + there is one default plan: " { + $defaultPlanName = "defaultPlan" + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="$defaultPlanName";Name=$defaultPlanName;Sku=@{Tier="Free"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with a NEW ResourceGroup with same name as the webapp." { + $result.ResourceGroupName | Should be $defaultName + $result.ResourceGroupName | Should be $result.Name + } + + It "Returns Site with default Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with the only EXISTING default plan." { + $result.AppServicePlan | Should be $defaultPlanName + } + } + + Context "[mock] When no parameters are provided and + there is multiple default plans: " { + $defaultPlanName1 = "defaultPlan1" + $defaultPlanName2 = "defaultPlan2" + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="$defaultPlanName1";Name=$defaultPlanName1;Sku=@{Tier="Free"};ResourceGroup="group2"} + $plan3 = @{Id="$defaultPlanName2";Name=$defaultPlanName2;Sku=@{Tier="Free"};ResourceGroup="group3"} + $plans = @($plan1,$plan2,$plan3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with a NEW ResourceGroup with same name as the webapp." { + $result.ResourceGroupName | Should be $defaultName + $result.ResourceGroupName | Should be $result.Name + } + + It "Returns Site with default Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with the first EXISTING default plan." { + $result.AppServicePlan | Should be $defaultPlanName1 + } + } + + Context "[mock] When group name is provided and + group with provided name exists and + default plan does not exist: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $existingGroupName = "existingGroupName" + $existingGroupLocation = "existingGroupLocation" + $group1 = @{ResourceGroupName=$existingGroupName;Location=$existingGroupLocation} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $true} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -ResourceGroupName $existingGroupName + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with EXISTING group with provided ResourceGroupName." { + $result.ResourceGroupName | Should be $existingGroupName + } + + It "Returns Site with the SAME Location as the existing resource group + that matches the provided ResourceGroupName." { + $result.Location | Should be $existingGroupLocation + } + + It "Returns Site with NEW AppServicePlan with the same name as the webapp." { + $result.AppServicePlan | Should be $defaultName + $result.AppServicePlan | Should be $result.Name + } + } + + Context "[mock] When group name is provided and + group with provided name does not exist and + default plan does not exist: " { + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $providedGroupName = "providedGroupName" + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -ResourceGroupName $providedGroupName + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with provided ResourceGroupName." { + $result.ResourceGroupName | Should be $providedGroupName + } + + It "Returns Site with the default Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with NEW AppServicePlan with the same name as the webapp." { + $result.AppServicePlan | Should be $defaultName + $result.AppServicePlan | Should be $result.Name + } + } + + Context "[mock] When plan name is provided and + plan with provided name does not exist: " { + $providedPlanName = "ProvidedPlanName" + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $providedPlanName + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with same name as the webapp." { + $result.ResourceGroupName | Should Be $defaultName + $result.ResourceGroupName | Should Be $result.Name + } + + It "Returns Site with the default Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with NEW AppServicePlan with the same name as the webapp." { + $result.AppServicePlan | Should be $providedPlanName + } + } + + + Context "[mock] When plan name is provided and + one plan with provided name exist: " { + $existingPlanName = "ExistingPlanName" + $existingPlanGroup = "ExistingPlanGroup" + $plan1 = @{Id=$existingPlanName;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingPlanGroup} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName + + It "Returns Site with default name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with same name as the webapp." { + $result.ResourceGroupName | Should Be $defaultName + $result.ResourceGroupName | Should Be $result.Name + } + + It "Returns Site with the default Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should be $existingPlanName + } + } + + Context "[mock] When plan name is provided and + multiple plans with provided name exist: " { + $existingPlanName = "ExistingPlanName" + $existingPlanGroup = "ExistingPlanGroup" + $plan1 = @{Id="plan1";Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + + + It "Should throw." { + {$result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName} | Should Throw + } + } + + + Context "[mock] When plan name and group name are provided and + no plan nor group with those names exist: " { + $providedPlanName = "PlanName" + $providedGroupName = "GroupNAme" + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $providedPlanName -ResourceGroupName $providedGroupName + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with same name provided." { + $result.ResourceGroupName | Should Be $providedGroupName + } + + It "Returns Site with the DEFAULT Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $providedPlanName + } + } + + Context "[mock] When plan name and group name are provided and + no group with that name exist and + plan with that name exist: " { + $existingPlanName = "ExistingPlanName" + $providedGroupName = "GroupNAme" + $plan1 = @{Id=$existingPlanName;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName -ResourceGroupName $providedGroupName + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with same name provided." { + $result.ResourceGroupName | Should Be $providedGroupName + } + + It "Returns Site with the DEFAULT Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan name and group name are provided and + no group with that name exist and + multiple plans with that name exist: " { + $existingPlanName = "ExistingPlanName" + $providedGroupName = "GroupNAme" + $plan1 = @{Id="plan1";Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup="group1"} + $plan2 = @{Id="plan2";Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName="rg2";Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $false} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + + It "Should throw." { + {$result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName -ResourceGroupName $providedGroupName} | Should Throw "There are various App Service Plans with that name" + } + } + + Context "[mock] When plan name and group name are provided and + group with that name exists + plan with that name exist and belongs to that group: " { + $existingPlanName = "ExistingPlanName" + $existingGroupName = "GroupNAme" + $existingGroupLocation = "locationgroup" + $plan1 = @{Id=$existingPlanName;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingGroupName} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingGroupName;Location=$existingGroupLocation} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $true} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName -ResourceGroupName $existingGroupName + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with EXISTING group with same name provided." { + $result.ResourceGroupName | Should Be $existingGroupName + } + + It "Returns Site with the location of EXISTING Location." { + $result.Location | Should be $existingGroupLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan name and group name are provided and + group with that name exists + plan with that name exist and belongs to another group: " { + $existingPlanName = "ExistingPlanName" + $existingPlanGroup = "ExistingPlanGroup" + $existingGroupName = "GroupNAme" + $existingGroupLocation = "locationgroup" + $plan1 = @{Id=$existingPlanName;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingPlanGroup} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup=$existingGroupName} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingGroupName;Location=$existingGroupLocation} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $true} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName -ResourceGroupName $existingGroupName + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with EXISTING group with same name provided." { + $result.ResourceGroupName | Should Be $existingGroupName + } + + It "Returns Site with the location of EXISTING Location." { + $result.Location | Should be $existingGroupLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan name and group name are provided and + group with that name exists + multiple plans with that name and + one belongs to the existing group: " { + $existingPlanName = "ExistingPlanName" + $existingPlanGroup = "ExistingPlanGroup" + $existingPlanGroupLocation = "locationgroup" + $plan1 = @{Id=$existingPlanName;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingPlanGroup} + $plan2 = @{Id="plan2";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingPlanGroup ;Location=$existingPlanGroupLocation} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $true} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanName -ResourceGroupName $existingPlanGroup + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with EXISTING group with same name provided." { + $result.ResourceGroupName | Should Be $existingPlanGroup + } + + It "Returns Site with the location of EXISTING Location." { + $result.Location | Should be $existingPlanGroupLocation + } + + It "Returns Site with EXISTING AppServicePlan name which belongs to the existing group." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan name and group name are provided and + group with that name exists and + plan with that name does not exist, and there is + a default plan: " { + $defaultPlanName = "DefaultPlanName" + $customPlan = "customPlan" + $existingGroup = "exisitingGroup" + $existingGroupLocation = "locationgroup" + $plan1 = @{Id="plan1";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id=$defaultPlanName;Name=$defaultPlanName;Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingGroup ;Location=$existingGroupLocation} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $true} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmAppServicePlan {return @{Id=$Name;Name=$Name;Location=$Location;Sku=@{Tier=$Tier};ResourcerGroupName=$ResourceGroupName}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $customPlan -ResourceGroupName $existingGroup + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with EXISTING group with same name provided." { + $result.ResourceGroupName | Should Be $existingGroup + } + + It "Returns Site with the location of EXISTING Location." { + $result.Location | Should be $existingGroupLocation + } + + It "Returns Site with EXISTING AppServicePlan name which belongs to the existing group." { + $result.AppServicePlan | Should Be $customPlan + } + } + + Context "[mock] When plan ID and group name are provided and + group with that name does not exist and + plan with that ID exist: " { + $existingPlanName = "existingPlan" + $existingPlanGroup = "existingPlanGroup" + $groupExistence = $false + $existingPlanId = "/subscriptions/f30a7701-df2c-1bc2-ba9d-pb11861cr13c/resourceGroups/$existingPlanGroup/providers/Microsoft.Web/serverfarms/$existingPlanName" + $providedGroupName = "ProvidedGroupName" + $plan1 = @{Id="plan1";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id=$existingPlanId;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingPlanGroup} + $plans = @($plan1,$plan2) + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingPlanGroup ;Location="loc2"} + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $groupExistence} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmResourceGroup {return @{ResourceGroupName=$Name;Location=$Location}} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanId -ResourceGroupName $providedGroupName + + It "Returns Site with DEFAULT name." { + $result.Name | Should be $defaultName + } + + It "Returns Site with NEW group with same name as the app." { + $result.ResourceGroupName | Should be $providedGroupName + } + + It "Returns Site with the location of DEFAULT Location." { + $result.Location | Should be $defaultLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan ID and group name are provided and + group with that name exists and + plan with that ID exist: " { + $existingPlanName = "existingPlan" + $existingPlanGroup = "existingPlanGroup" + $existingPlanId = "/subscriptions/f30a7701-df2c-1bc2-ba9d-pb11861cr13c/resourceGroups/$existingPlanGroup/providers/Microsoft.Web/serverfarms/$existingPlanName" + $groupExistence = $true + $plan1 = @{Id="plan1";Name="plan2";Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id=$existingPlanId;Name=$existingPlanName;Sku=@{Tier="Basic"};ResourceGroup=$existingPlanGroup} + $plans = @($plan1,$plan2) + $groupLocation = "groupLocation" + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingPlanGroup ;Location=$groupLocation } + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $groupExistence} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + $result = New-AzWebAppJustDoIt -AppServicePlan $existingPlanId -ResourceGroupName $existingPlanGroup + + It "Returns Site with DEFAULT name." { + $result.Name | Should Be $defaultName + } + + It "Returns Site with NEW group with same name as the app." { + $result.ResourceGroupName | Should Be $existingPlanGroup + } + + It "Returns Site with the location of DEFAULT Location." { + $result.Location | Should Be $groupLocation + } + + It "Returns Site with EXISTING AppServicePlan name." { + $result.AppServicePlan | Should Be $existingPlanName + } + } + + Context "[mock] When plan ID and group name are provided and + group with that name exists and + plan with that ID DOES NOT exist: " { + $providedPlanName = "ProvidedPlanName" + $providedPlanGroup = "ProvidedPlanGroup" + $providedPlanId = "/subscriptions/f30a7701-df2c-1bc2-ba9d-pb11861cr13c/resourceGroups/$providedPlanName/providers/Microsoft.Web/serverfarms/$providedPlanGroup" + $groupExistence = $true + $plan1 = @{Id="plan1";Name="plan1";Sku=@{Tier="Free"};ResourceGroup="group1"} + $plan2 = @{Id="plan1";Name="plan2";Sku=@{Tier="Basic"};ResourceGroup="group2"} + $plans = @($plan1,$plan2) + $existingGroup = "Existing Group" + $groupLocation = "groupLocation" + $group1 = @{ResourceGroupName="rg1";Location="loc1"} + $group2 = @{ResourceGroupName=$existingGroup ;Location=$groupLocation } + $group3 = @{ResourceGroupName="rg3";Location="loc3"} + $groups = @($group1, $group2, $group3) + Mock Test-NameAvailability {return $true} + Mock Test-ResourceGroupExistence {return $groupExistence} + Mock Get-AzureRmAppServicePlan {return Get-AzureRmAppServicePlanMock $Name $ResourceGroupName $plans} + Mock Get-AzureRmResourceGroup {return Get-AzureRmResourceGroupMock $Name $groups} + Mock New-AzureRmWebApp {return @{Name=$Name;ResourceGroupName=$ResourceGroupName;AppServicePlan=$AppServicePlan;Location=$Location}} + + It "Should Throw." { + {$result = New-AzWebAppJustDoIt -AppServicePlan $providedPlanId -ResourceGroupName $existingGroup} | Should Throw "The app service plan with the id provided does not exist" + } + } + + Context "[mock] When NON-VALID LOCATION is provided: " { + $nonValidLocation = "customLocation" + + It "Should throw." { + {$result = New-AzWebAppJustDoIt -ResourceGroupName $existingGroup.ResourceGroupName -Location $nonValidLocation} | Should Throw + } + } + } +} diff --git a/experiments/Websites.Experiments/AzureRM.Websites.Experiments.format.ps1xml b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.format.ps1xml new file mode 100644 index 000000000000..4fae04944e6a --- /dev/null +++ b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.format.ps1xml @@ -0,0 +1,44 @@ + + + + + Microsoft.Azure.Management.WebSites.Models.Site + + Microsoft.Azure.Management.WebSites.Models.Site + + + + + + + SiteName + + + ResourceGroup + + + + ($_.ServerFarmId.split('/'))[($_.ServerFarmId.split('/')).Count - 1] + + + Location + + + + DefaultHostName + + + + ($_.EnabledHostNames[1]) + + + + Learn how to deploy the files for your web app to Azure App Service following this link https://docs.microsoft.com/en-us/azure/app-service-web/web-sites-deploy + + + + + + + + diff --git a/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psd1 b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psd1 new file mode 100644 index 000000000000..e592e3e007d4 Binary files /dev/null and b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psd1 differ diff --git a/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psm1 b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psm1 new file mode 100644 index 000000000000..4edb2f01cdad --- /dev/null +++ b/experiments/Websites.Experiments/AzureRM.Websites.Experiments.psm1 @@ -0,0 +1,1043 @@ +# ---------------------------------------------------------------------------------- +# +# 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. +# ---------------------------------------------------------------------------------- + +function New-AzWebAppJustDoIt +{ + [CmdletBinding()] + [OutputType([Microsoft.Azure.Management.WebSites.Models.Site])] + param( + [string][Parameter(Mandatory=$false)][alias("Name")]$WebAppName, + [string][Parameter(Mandatory=$false)][alias("Group")]$ResourceGroupName, + [string][Parameter(Mandatory=$false)][alias("Plan")]$AppServicePlan + ) + DynamicParam{ + #Set the dynamic parameters' name + $ParamName_location = 'Location' + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.Mandatory = $false + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + #Generate and set the ValidateSet + $providerNamespace = "Microsoft.Web" + try + { + $availableLocations = $(Get-AzureRmResourceProvider | Where-Object {$_.ProviderNamespace -eq $providerNamespace}).Locations + } + catch + { + throw $_ + } + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($availableLocations) + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParamName_location, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParamName_location, $RuntimeParameter) + + return $RuntimeParameterDictionary + } + + BEGIN { + $context = Get-Context + $webSitesClient = Get-WebSitesClient $context + $resourceManagementClient = Get-ResourceManagementClient $context + } + + PROCESS { + $mainActivity = "Create Azure Web App" + [string]$Location = $PSBoundParameters[$ParamName_location] + Write-Progress ` + -Activity "Some Activity." ` + -CurrentOperation "Getting App Name information." + [string]$appName = Get-WebAppName $PSBoundParameters $webSitesClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting Resource Group information." + $operationNumber = 2 + [hashtable]$groupInfo = Get-ResourceGroupInfo $PSBoundParameters $appName $resourceManagementClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Service Plan information." + $operationNumber = 3 + [hashtable]$appPlanInfo = Get-AppServicePlanInfo $PSBoundParameters $appName $groupInfo.Name + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Location information." + $operationNumber++ + [string]$appLocation = Get-AppLocation $PSBoundParameters $groupInfo.Name $groupInfo.Exists $availableLocations + if ($groupInfo.Exists) { + $appGroup = Get-AzureRmResourceGroup ` + -Name $groupInfo.Name + $message = "Using resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $appGroup = New-AzureRmResourceGroup ` + -Name $groupInfo.Name ` + -Location $appLocation + $message = "Created resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } + + $operationNumber = 4 + if ($appPlanInfo.Exists) { + $appPlan = Get-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Using app service plan '$($appPlan.Name)' in location '$($appPlan.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $defaultTier = "Free" + $appPlan = New-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -Location $appLocation ` + -Tier $defaultTier ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Created app service plan '$($appPlan.Name)' in location '$($appPlan.Location)' with Tier '$($appPlan.Sku.Tier)'." + Write-Information -MessageData $message -InformationAction Continue + } + + $webapp = New-AzureRmWebApp ` + -Name $appName ` + -AppServicePlan $appPlan.Id ` + -ResourceGroupName $appGroup.ResourceGroupName ` + -Location $appLocation + + Write-Output $webapp + } + + END {} +} + +function New-AzWebApp +{ + [CmdletBinding()] + [OutputType([Microsoft.Azure.Management.WebSites.Models.Site])] + param( + [string][Parameter(Mandatory=$false)][alias("Name")]$WebAppName, + [string][Parameter(Mandatory=$false)][alias("Group")]$ResourceGroupName, + [string][Parameter(Mandatory=$false)][alias("Plan")]$AppServicePlan, + [switch][Parameter(Mandatory=$false)]$Auto, + [switch][Parameter(Mandatory=$false)]$AddRemote, + [string][Parameter(Mandatory=$false)]$GitRepositoryPath + ) + DynamicParam{ + #Set the dynamic parameters' name + $ParamName_location = 'Location' + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.Mandatory = $false + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + #Generate and set the ValidateSet + $providerNamespace = "Microsoft.Web" + try + { + $availableLocations = $(Get-AzureRmResourceProvider | Where-Object {$_.ProviderNamespace -eq $providerNamespace}).Locations + } + catch + { + throw $_ + } + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($availableLocations) + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParamName_location, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParamName_location, $RuntimeParameter) + + return $RuntimeParameterDictionary + } + + BEGIN { + $context = Get-Context + $webSitesClient = Get-WebSitesClient $context + $resourceManagementClient = Get-ResourceManagementClient $context + } + + PROCESS { + #Validate Parameters + if (-not $PSBoundParameters.ContainsKey('Auto')) { + $parametersNotProvided = @() + if(-not $PSBoundParameters.ContainsKey('WebAppName')){ + $parametersNotProvided += 'WebAppName' + } + + if(-not $PSBoundParameters.ContainsKey('ResourceGroupName')){ + $parametersNotProvided += 'ResourceGroupName' + } + + if(-not $PSBoundParameters.ContainsKey('AppServicePlan')){ + $parametersNotProvided += 'AppServicePlan' + } + + if(-not $PSBoundParameters.ContainsKey('Location')){ + $parametersNotProvided += 'Location' + } + + $message = "The following parameters were not provided: " + $message += $($parametersNotProvided -join ',') + " ." + $message += "You can provide -Auto switch to use Smart Defaults." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } + + $mainActivity = "Create Azure Web App" + [string]$Location = $PSBoundParameters[$ParamName_location] + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Name information." + [string]$appName = Get-WebAppName ` + -ProvidedParameters $PSBoundParameters ` + -WebSitesClient $webSitesClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting Resource Group information." + [hashtable]$groupInfo = Get-ResourceGroupInfo ` + -ProvidedParameters $PSBoundParameters ` + -WebAppName $appName ` + -ResourceManagementClient $resourceManagementClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Service Plan information." + [hashtable]$appPlanInfo = Get-AppServicePlanInfo ` + -ProvidedParameters $PSBoundParameters ` + -WebAppName $appName ` + -ResourceGroupName $groupInfo.Name + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Location information." + [string]$appLocation = Get-AppLocation ` + -ProvidedParameters $PSBoundParameters ` + -ResourceGroupName $groupInfo.Name` + -ResourceGroupExists $groupInfo.Exists ` + -AvailableLocations $availableLocations + if ($groupInfo.Exists) { + $appGroup = Get-AzureRmResourceGroup ` + -Name $groupInfo.Name + $message = "Using resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $appGroup = New-AzureRmResourceGroup ` + -Name $groupInfo.Name ` + -Location $appLocation + $message = "Created resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } + + if ($appPlanInfo.Exists) { + $appPlan = Get-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Using app service plan '$($appPlan.Name)' in location '$($appPlan.Location)' with Tier '$($appPlan.Sku.Tier)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $defaultTier = "Free" + $appPlan = New-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -Location $appLocation ` + -Tier $defaultTier ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Created app service plan '$($appPlan.Name)' in location '$($appPlan.Location)' with Tier '$($appPlan.Sku.Tier)'." + Write-Information -MessageData $message -InformationAction Continue + } + + $webapp = New-AzureRmWebApp ` + -Name $appName ` + -AppServicePlan $appPlan.Id ` + -ResourceGroupName $appGroup.ResourceGroupName ` + -Location $appLocation + + Write-Output $webapp + + if (($PSBoundParameters.ContainsKey('AddRemote') -or $PSBoundParameters.ContainsKey('Auto')) -and $webapp) { + Add-Remote -ProvidedParameters $PSBoundParameters -WebApp $webapp -GitRepositoryPath $GitRepositoryPath + } + } + + END {} +} + +function Add-Remote +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [Microsoft.Azure.Management.WebSites.Models.Site][Parameter()]$WebApp, + [string][Parameter()] $GitRepositoryPath + ) + [bool]$repoDetected = $true + [bool]$repoAdded = $true + $OriginalErrorActionPreference = $ErrorActionPreference + + if(-Not $ProvidedParameters.ContainsKey('GitRepositoryPath')){ + $GitRepositoryPath = (Get-Location).Path + } + + try + { + $ErrorActionPreference = 'Stop' + git -C $GitRepositoryPath status | Out-Null + } + catch + { + $repoDetected = $false + } + finally + { + $ErrorActionPreference = $OriginalErrorActionPreference + } + + if ($repoDetected) { + $message = "A git repository has been detected. " + try + { + $ErrorActionPreference = 'Stop' + # Get app-level deployment credentials + $xml = [xml](Get-AzureRmWebAppPublishingProfile -Name $WebApp.Name -ResourceGroupName $WebApp.ResourceGroup -OutputFile null) + $username = $xml.SelectNodes("//publishProfile[@publishMethod=`"MSDeploy`"]/@userName").value + $password = $xml.SelectNodes("//publishProfile[@publishMethod=`"MSDeploy`"]/@userPWD").value + $remoteName = "azure" + # Add the Azure remote to a local Git respository + $command = "git -C $GitRepositoryPath remote add $remoteName 'https://${username}:$password@$($WebApp.EnabledHostNames[0])'" + " 2> $gitOutput" + Invoke-Expression -Command $command | Out-Null + if ($gitOutPut) { + $repoAdded = $false + } + } + catch + { + $repoAdded = $false + } + finally + { + $ErrorActionPreference = $OriginalErrorActionPreference + } + + if ($repoAdded) { + $message += "Added remote '$($remoteName)'. Push your code by running the command 'git push $($remoteName) master.' " + } else { + $message += "However, remote '$($remoteName)' could not be added. " + } + + Write-Information $message -InformationAction Continue + } +} + +function Get-WebAppName +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [Microsoft.Azure.Commands.Websites.Experiments.CustomWebSiteManagementClient][Parameter()]$WebSitesClient + ) + [string]$name = "" + [bool]$nameIsAvailable = $false + + if ($ProvidedParameters.ContainsKey('WebAppName')) { + $name = $ProvidedParameters.WebAppName + $nameIsAvailable = Test-NameAvailability $name $WebSitesClient + if (-not $NameIsAvailable) { + $message = "Website with given name '$name' already exists." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } + } else { + for ($i = 0; $i -le 2; $i++) { + $name ="WebApp$(Get-Random -max 1000000)" + $nameIsAvailable = Test-NameAvailability $name $WebSitesClient + if ($NameIsAvailable) { + break + } + } + } + return $name +} + +function Test-NameAvailability +{ + param( + [string][Parameter()]$WebAppName, + [Microsoft.Azure.Commands.Websites.Experiments.CustomWebSiteManagementClient][Parameter()]$WebSitesClient + ) + [string]$resourceType = "Site" + return $WebSitesClient.CheckNameAvailabilityWithHttpMessagesAsync($WebAppName, $resourceType).Result.Body.NameAvailable +} + +function Get-ResourceGroupInfo +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter(Mandatory=$false)]$WebAppName, + [Microsoft.Azure.Management.ResourceManager.ResourceManagementClient][Parameter()]$ResourceManagementClient + ) + [hashtable]$resourceGroupInfo = @{Name="";Exists=$false} + $defaultName = $WebAppName + + if ($ProvidedParameters.ContainsKey('ResourceGroupName')) { + $resourceGroupInfo.Name = $ProvidedParameters.ResourceGroupName + } else { + $resourceGroupInfo.Name = $defaultName + } + + $resourceGroupInfo.Exists = Test-ResourceGroupExistence $resourceGroupInfo.Name $ResourceManagementClient + + return $resourceGroupInfo +} + +function Test-ResourceGroupExistence +{ + param( + [string][Parameter()]$ResourceGroupName, + [Microsoft.Azure.Management.ResourceManager.ResourceManagementClient][Parameter()]$ResourceManagementClient + ) + return $ResourceManagementClient.ResourceGroups.CheckExistenceWithHttpMessagesAsync($ResourceGroupName).Result.Body +} + +function Get-AppServicePlanInfo +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter()]$WebAppName, + [string][Parameter()]$ResourceGroupName + ) + [hashtable]$appServicePlanInfo = @{Name="";ResourceGroup="";IsDefaultPlan=$false;Exists=$false} + [object[]]$appServicePlans = Get-AzureRmAppServicePlan + $defaultName = $WebAppName + + if ($ProvidedParameters.ContainsKey('AppServicePlan')) { + $regexp = '/subscriptions/[-A-Za-z0-9]+/resourceGroups/[-\w\._\(\)]+/providers/Microsoft.Web/serverfarms/[-\w\._\(\)]+$' + $idWasProvided = $ProvidedParameters.AppServicePlan -imatch $regexp + if ($idWasProvided) { + $parsedId = $ProvidedParameters.AppServicePlan.split('/') + $appServicePlanInfo.Name = $parsedId[$parsedId.Length - 1] + $appServicePlanInfo.ResourceGroup = $parsedId[4] + $existingPlan = $appServicePlans | Where-Object {$_.Id -eq $ProvidedParameters.AppServicePlan} + if (-not $existingPlan) { + $message = "The app service plan with the id provided does not exist." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } + } else { + $appServicePlanInfo.Name = $ProvidedParameters.AppServicePlan + } + $appServicePlanInfo.IsDefaultPlan = $false + } else { + $existentDefaultPlan = Get-DefaultAppServicePlan $AppServicePlans + if ($existentDefaultPlan) { + $appServicePlanInfo.Name = $existentDefaultPlan.Name + $appServicePlanInfo.ResourceGroup = $existentDefaultPlan.ResourceGroup + $appServicePlanInfo.IsDefaultPlan = $true + $appServicePlanInfo.Exists = $true + } else { + $appServicePlanInfo.Name = $defaultName + $appServicePlanInfo.IsDefaultPlan = $false + } + } + + if (-not $appServicePlanInfo.IsDefaultPlan) { + [object[]]$appServicePlansWithProvidedName = $appServicePlans | Where-Object {$_.Name -eq $appServicePlanInfo.Name} + if ($appServicePlansWithProvidedName) { + $appServicePlanInfo.Exists = $true + $appServicePlanWithProvidedNameAndGroup = $appServicePlansWithProvidedName | Where-Object {$_.ResourceGroup -eq $ResourceGroupName} + if ($appServicePlanWithProvidedNameAndGroup) { + $appServicePlanInfo.ResourceGroup = $appServicePlanWithProvidedNameAndGroup.ResourceGroup + } else { + if ($appServicePlansWithProvidedName.Count -gt 1) { + $message = "There are various App Service Plans with that name. An existing Resource Group name should be provided." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } else { + $appServicePlanInfo.ResourceGroup = $appServicePlansWithProvidedName.ResourceGroup + } + } + } else { + $appServicePlanInfo.Exists = $false + $appServicePlanInfo.ResourceGroup = $ResourceGroupName + } + } + + return $appServicePlanInfo +} + +function Get-DefaultAppServicePlan +{ + param( + [object[]][Parameter()]$AppServicePlans + ) + [object[]]$appServicePlanMatches = $AppServicePlans | Where-Object {$_.Sku.Tier -eq "Free"} + if($appServicePlanMatches){ + return $appServicePlanMatches[0] + } else { + return $null + } +} + +function Get-AppLocation +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter()]$ResourceGroupName, + [bool][Parameter()]$ResourceGroupExists, + [string[]][Parameter()]$AvailableLocations + ) + [string]$location = "" + + if ($ProvidedParameters.ContainsKey('Location')) { + $location = $ProvidedParameters.Location + } else { + if ($ResourceGroupExists) { + $location = $(Get-AzureRmResourceGroup -Name $ResourceGroupName).Location + } else { + $location = Get-DefaultLocation $AvailableLocations + } + } + return $location +} + +function Get-DefaultLocation +{ + param( + [string[]][Parameter()]$AvailableLocations + ) + # TODO: figure out a way to get a 'Smart Default Location' + return $AvailableLocations[0] +} + +function Get-Context +{ + return [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext +} + +function Get-ResourceManagementClient +{ + param( + [Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContext] $Context + ) + $factory = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.ClientFactory + [System.Type[]]$types = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContext], [string] + $resourceManagementClient = [Microsoft.Azure.Management.ResourceManager.ResourceManagementClient] + $method = [Microsoft.Azure.Commands.Common.Authentication.IClientFactory].GetMethod("CreateArmClient", $types) + + $closedMethod = $method.MakeGenericMethod($resourceManagementClient) + $arguments = $Context, [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureEnvironment+Endpoint]::ResourceManager + $client = $closedMethod.Invoke($factory, $arguments) + + return $client +} + +function Get-WebSitesClient +{ + param( + [Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContext] $Context + ) + $factory = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.ClientFactory + [System.Type[]]$types = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContext], [string] + $webSitesClient = [Microsoft.Azure.Commands.Websites.Experiments.CustomWebSiteManagementClient] + $method = [Microsoft.Azure.Commands.Common.Authentication.IClientFactory].GetMethod("CreateArmClient", $types) + + $closedMethod = $method.MakeGenericMethod($webSitesClient) + $arguments = $context, [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureEnvironment+Endpoint]::ResourceManager + $client = $closedMethod.Invoke($factory, $arguments) + + return $client +} + +function New-AzWebAppGrayParam +{ + [CmdletBinding()] + [OutputType([Microsoft.Azure.Management.WebSites.Models.Site])] + param( + [string][Parameter(Mandatory=$false)][alias("Name")]$WebAppName, + [string][Parameter(Mandatory=$false)][alias("Group")]$ResourceGroupName, + [string][Parameter(Mandatory=$false)][alias("Plan")]$AppServicePlan, + [switch][Parameter(Mandatory=$false)]$Auto, + [switch][Parameter(Mandatory=$false)]$AddRemote, + [string][Parameter(Mandatory=$false)]$GitRepositoryPath + ) + DynamicParam{ + #Set the dynamic parameters' name + $ParamName_location = 'Location' + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + if ($PSBoundParameters.ContainsKey('Auto')) { + $ParameterAttribute.Mandatory = $false + } else { + $ParameterAttribute.Mandatory = $true + } + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + #Generate and set the ValidateSet + $providerNamespace = "Microsoft.Web" + try + { + $availableLocations = $(Get-AzureRmResourceProvider | Where-Object {$_.ProviderNamespace -eq $providerNamespace}).Locations + } + catch + { + throw $_ + } + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($availableLocations) + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParamName_location, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParamName_location, $RuntimeParameter) + + return $RuntimeParameterDictionary + } + + BEGIN { + $context = Get-Context + $webSitesClient = Get-WebSitesClient $context + $resourceManagementClient = Get-ResourceManagementClient $context + } + + PROCESS { + $mainActivity = "Create Azure Web App" + [string]$Location = $PSBoundParameters[$ParamName_location] + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Name information." + [string]$appName = Get-WebAppNameGrayParam $PSBoundParameters $webSitesClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting Resource Group information." + [hashtable]$groupInfo = Get-ResourceGroupInfoGrayParam $PSBoundParameters $appName $resourceManagementClient + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Service Plan information." + [hashtable]$appPlanInfo = Get-AppServicePlanInfoGrayParam $PSBoundParameters $appName $groupInfo.Name + Write-Progress ` + -Activity $mainActivity ` + -CurrentOperation "Getting App Location information." + [string]$appLocation = Get-LocationGrayParam $PSBoundParameters $groupInfo.Name $groupInfo.Exists $availableLocations + if ($groupInfo.Exists) { + $appGroup = Get-AzureRmResourceGroup ` + -Name $groupInfo.Name + $message = "Using resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $appGroup = New-AzureRmResourceGroup ` + -Name $groupInfo.Name ` + -Location $appLocation + $message = "Created resource group '$($appGroup.ResourceGroupName)' in location '$($appGroup.Location)'." + Write-Information -MessageData $message -InformationAction Continue + } + + if ($appPlanInfo.Exists) { + $appPlan = Get-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Using app service plan '$($appPlan.Name)' in location '$($appPlan.Location)' with Tier '$($appPlan.Sku.Tier)'." + Write-Information -MessageData $message -InformationAction Continue + } else { + $defaultTier = "Free" + $appPlan = New-AzureRmAppServicePlan ` + -Name $appPlanInfo.Name ` + -Location $appLocation ` + -Tier $defaultTier ` + -ResourceGroupName $appPlanInfo.ResourceGroup + $message = "Created app service plan '$($appPlan.Name)' in location '$($appPlan.Location)' with Tier '$($appPlan.Sku.Tier)'." + Write-Information -MessageData $message -InformationAction Continue + } + + $webapp = New-AzureRmWebApp ` + -Name $appName ` + -AppServicePlan $appPlan.Id ` + -ResourceGroupName $appGroup.ResourceGroupName ` + -Location $appLocation + + Write-Output $webapp + + Add-RemoteGrayParam -ProvidedParameters $PSBoundParameters -WebApp $webapp -GitRepositoryPath $GitRepositoryPath + } + + END {} +} + +function Add-RemoteGrayParam +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [Microsoft.Azure.Management.WebSites.Models.Site][Parameter()]$WebApp, + [string][Parameter()] $GitRepositoryPath + ) + [bool]$repoDetected = $true + [bool]$repoAdded = $true + $OriginalErrorActionPreference = $ErrorActionPreference + + if(-Not $ProvidedParameters.ContainsKey('GitRepositoryPath')){ + $GitRepositoryPath = (Get-Location).Path + } + + try + { + $ErrorActionPreference = 'Stop' + git -C $GitRepositoryPath status | Out-Null + } + catch + { + $repoDetected = $false + } + finally + { + $ErrorActionPreference = $OriginalErrorActionPreference + } + + if ($repoDetected) { + $message = "A git repository has been detected. " + try + { + $ErrorActionPreference = 'Stop' + + # Get app-level deployment credentials + $xml = [xml](Get-AzureRmWebAppPublishingProfile -Name $WebApp.Name -ResourceGroupName $WebApp.ResourceGroup -OutputFile null) + $username = $xml.SelectNodes("//publishProfile[@publishMethod=`"MSDeploy`"]/@userName").value + $password = $xml.SelectNodes("//publishProfile[@publishMethod=`"MSDeploy`"]/@userPWD").value + + # Add remote azure + $remoteName = "azure" + if ($ProvidedParameters.ContainsKey('Auto') -or $ProvidedParameters.ContainsKey('AddRemote')){ + Write-Information $message -InformationAction Continue + } else { + $title = $message + $message = "Would you like to add this webapp as a remote named '$remoteName'?" + $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", ` + "Adds this webapp as a remote named '$remoteName'" + $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", ` + "No action is taken" + $options = [System.Management.Automation.Host.ChoiceDescription[]]($no, $yes) + $result = $host.ui.PromptForChoice($title, $message, $options, 0) + } + + if ($result -eq 1 -or $ProvidedParameters.ContainsKey('AddRemote') -or $ProvidedParameters.ContainsKey('Auto')) { + # Add the Azure remote to a local Git respository + $command = "git -C $GitRepositoryPath remote add $remoteName 'https://${username}:$password@$($WebApp.EnabledHostNames[0])'" + " 2> $gitOutput" + Invoke-Expression -Command $command | Out-Null + + } + + if ($gitOutPut) { + $repoAdded = $false + } + } + catch + { + $repoAdded = $false + } + finally + { + $ErrorActionPreference = $OriginalErrorActionPreference + } + + if ($repoAdded) { + $message = "Added remote '$($remoteName)'. Push your code by running the command 'git push $($remoteName) master.' " + } else { + $message = "Remote '$($remoteName)' could not be added. " + } + + Write-Information $message -InformationAction Continue + } +} + +function Get-WebAppNameGrayParam +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [Microsoft.Azure.Commands.Websites.Experiments.CustomWebSiteManagementClient][Parameter()]$WebSitesClient + ) + [string]$name = "" + [bool]$nameIsAvailable = $false + + if ($ProvidedParameters.ContainsKey('WebAppName')) { + $name = $ProvidedParameters.WebAppName + $nameIsAvailable = Test-NameAvailability $name $WebSitesClient + if (-not $NameIsAvailable) { + $message = "Website with given name '$name' already exists." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } + } else { + for ($i = 0; $i -le 2; $i++) { + $defaultName ="WebApp$(Get-Random -max 1000000)" + $nameIsAvailable = Test-NameAvailability $defaultName $WebSitesClient + if ($NameIsAvailable) { + break + } + } + + if ($ProvidedParameters.ContainsKey('Auto')) { + $name = $defaultName + } else { + $name = Get-WebAppNameFromUser $defaultName + } + } + + return $name +} + +function Get-WebAppNameFromUser +{ + param( + [string][Parameter()]$DefaultName + ) + + $selection = Read-Host "Enter a name for you WebApp or leave blank for default($defaultName)" + if ($selection) { + $nameIsAvailable = Test-NameAvailability $selection $WebSitesClient + if (-not $NameIsAvailable) { + $message = "Website with given name '$selection' already exists." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } else { + $name = $selection + } + } else { + $name = $DefaultName + } + + return $name +} + + +function Get-ResourceGroupInfoGrayParam +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter(Mandatory=$false)]$WebAppName, + [Microsoft.Azure.Management.ResourceManager.ResourceManagementClient][Parameter()]$ResourceManagementClient + ) + [hashtable]$resourceGroupInfo = @{Name="";Exists=$false} + $defaultName = $WebAppName + + if ($ProvidedParameters.ContainsKey('ResourceGroupName')) { + $resourceGroupInfo.Name = $ProvidedParameters.ResourceGroupName + } else { + if ($ProvidedParameters.ContainsKey('Auto')) { + $resourceGroupInfo.Name = $defaultName + } else { + $resourceGroupInfo.Name = Get-ResourceGroupNameFromUser $defaultName + } + + } + + $resourceGroupInfo.Exists = Test-ResourceGroupExistence $resourceGroupInfo.Name $ResourceManagementClient + + return $resourceGroupInfo +} + +function Get-ResourceGroupNameFromUser +{ + param( + [string][Parameter()]$DefaultName + ) + [object[]]$resourceGroups = Get-AzureRmResourceGroup + Write-Host "Resource Group options: " + Write-Host "[Default] $DefaultName" + for ($i = 1; $i -le $resourceGroups.Count; $i++) { + Write-Host "[$i] $($resourceGroups[$i-1].ResourceGroupName)" + } + + $selection = Read-Host "Enter your selection or a new resource group name (leave blank for default)" + if ($selection) { + if ($selection -match '^\d+$' -and $selection -le $resourceGroups.Count -and $selection -gt 0) { + $name = $resourceGroups[$selection - 1].ResourceGroupName + } else { + $name = $selection + } + } else { + $name = $DefaultName + } + + return $name +} + +function Get-AppServicePlanInfoGrayParam +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter()]$WebAppName, + [string][Parameter()]$ResourceGroupName + ) + [hashtable]$appServicePlanInfo = @{Name="";ResourceGroup="";IsDefaultPlan=$false;Exists=$false} + [object[]]$appServicePlans = Get-AzureRmAppServicePlan + $defaultName = $WebAppName + + if ($ProvidedParameters.ContainsKey('AppServicePlan')) { + $regexp = '/subscriptions/[-A-Za-z0-9]+/resourceGroups/[-\w\._\(\)]+/providers/Microsoft.Web/serverfarms/[-\w\._\(\)]+$' + $idWasProvided = $ProvidedParameters.AppServicePlan -imatch $regexp + if ($idWasProvided) { + $parsedId = $ProvidedParameters.AppServicePlan.split('/') + $appServicePlanInfo.Name = $parsedId[$parsedId.Length - 1] + $appServicePlanInfo.ResourceGroup = $parsedId[4] + $existingPlan = $appServicePlans | Where-Object {$_.Id -eq $ProvidedParameters.AppServicePlan} + if (-not $existingPlan) { + $message = "The app service plan with the id provided does not exist." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } + } else { + $appServicePlanInfo.Name = $ProvidedParameters.AppServicePlan + } + $appServicePlanInfo.IsDefaultPlan = $false + } else { + if($ProvidedParameters.ContainsKey('Auto')){ + $existentDefaultPlan = Get-DefaultAppServicePlan $appServicePlans + if ($existentDefaultPlan) { + $appServicePlanInfo.Name = $existentDefaultPlan.Name + $appServicePlanInfo.ResourceGroup = $existentDefaultPlan.ResourceGroup + $appServicePlanInfo.IsDefaultPlan = $true + $appServicePlanInfo.Exists = $true + } else { + $appServicePlanInfo.Name = $defaultName + $appServicePlanInfo.IsDefaultPlan = $false + } + } else { + $appServicePlanInfo = Get-AppServicePlanInfoFromUser $appServicePlans $defaultName + } + } + + if (-not $appServicePlanInfo.IsDefaultPlan) { + [object[]]$appServicePlansWithProvidedName = $appServicePlans | Where-Object {$_.Name -eq $appServicePlanInfo.Name} + if ($appServicePlansWithProvidedName) { + $appServicePlanInfo.Exists = $true + $appServicePlanWithProvidedNameAndGroup = $appServicePlansWithProvidedName | Where-Object {$_.ResourceGroup -eq $ResourceGroupName} + if ($appServicePlanWithProvidedNameAndGroup) { + $appServicePlanInfo.ResourceGroup = $appServicePlanWithProvidedNameAndGroup.ResourceGroup + } else { + if ($appServicePlansWithProvidedName.Count -gt 1) { + $message = "There are various App Service Plans with that name. An existing Resource Group name should be provided." + $exception = New-Object -TypeName System.Exception -ArgumentList $message + throw $exception + } else { + $appServicePlanInfo.ResourceGroup = $appServicePlansWithProvidedName.ResourceGroup + } + } + } else { + $appServicePlanInfo.Exists = $false + $appServicePlanInfo.ResourceGroup = $ResourceGroupName + } + } + + return $appServicePlanInfo +} + +function Get-AppServicePlanInfoFromUser +{ + param( + [object[]]$Plans, + [string]$DefaultName + ) + [hashtable]$appServicePlanInfo = @{Name="";ResourceGroup="";IsDefaultPlan=$false;Exists=$false} + $existentDefaultPlan = Get-DefaultAppServicePlan $Plans + + Write-Host "Plan options:" + if ($existentDefaultPlan) { + Write-Host "[Default] $($existentDefaultPlan.Name) {Tier=$($existentDefaultPlan.Sku.Tier);Location=$($existentDefaultPlan.Location)}" + } else { + Write-Host "[Default] $($defaultName) {Tier=Free}" + } + + for ($i = 1; $i -le $Plans.Count; $i++) { + Write-Host "[$i] $($Plans[$i-1].Name) {Tier=$($Plans[$i-1].Sku.Tier);Location=$($Plans[$i-1].Location)}" + } + + $selection = Read-Host "Enter your selection (leave blank for default)" + if ($selection) { + if ($selection -match '^\d+$' -and $selection -le $Plans.Count -and $selection -gt 0) { + $appServicePlanInfo.Name = $Plans[$selection - 1].Name + $appServicePlanInfo.IsDefaultPlan = $false + } else { + $appServicePlanInfo.Name = $selection + $appServicePlanInfo.IsDefaultPlan = $false + } + } else { + if ($existentDefaultPlan) { + $appServicePlanInfo.Name = $existentDefaultPlan.Name + $appServicePlanInfo.ResourceGroup = $existentDefaultPlan.ResourceGroup + $appServicePlanInfo.IsDefaultPlan = $true + $appServicePlanInfo.Exists = $true + } else { + $appServicePlanInfo.Name = $defaultName + $appServicePlanInfo.IsDefaultPlan = $false + } + } + + return $appServicePlanInfo + } + +function Get-LocationGrayParam +{ + param( + [hashtable][Parameter()]$ProvidedParameters, + [string][Parameter()]$ResourceGroupName, + [bool][Parameter()]$ResourceGroupExists, + [string[]][Parameter()]$AvailableLocations + ) + [string]$location = "" + + if ($ProvidedParameters.ContainsKey('Location')) { + $location = $ProvidedParameters.Location + } else { + if ($ResourceGroupExists) { + $location = $(Get-AzureRmResourceGroup -Name $ResourceGroupName).Location + } else { + $location = Get-DefaultLocation $AvailableLocations + } + } + + return $location +} + +function Get-LocationFromUser +{ + param( + [string][Parameter()]$DefaultLocation, + [string[]][Parameter()]$AvailableLocations + ) + Write-Host "WebApp Location options: " + Write-Host "[Default] $DefaultLocation" + for ($i = 1; $i -le $AvailableLocations.Count; $i++) { + Write-Host "[$i] $($AvailableLocations[$i-1])" + } + + $selection = Read-Host "Enter your selection (leave blank for default)" + if ($selection) { + if ($selection -match '^\d+$' -and $selection -le $AvailableLocations.Count -and $selection -gt 0) { + $location = $AvailableLocations[$selection - 1] + } else { + $location = $selection + } + } else { + $location = $DefaultLocation + } + + return $location +} + +Export-ModuleMember -Cmdlet New-AzWebAppJustDoIt +Export-ModuleMember -Cmdlet New-AzWebApp +Export-ModuleMember -Cmdlet New-AzWebAppGrayParam + diff --git a/experiments/Websites.Experiments/CustomWebSiteManagementClient.cs b/experiments/Websites.Experiments/CustomWebSiteManagementClient.cs new file mode 100644 index 000000000000..1554de5aa4ba --- /dev/null +++ b/experiments/Websites.Experiments/CustomWebSiteManagementClient.cs @@ -0,0 +1,510 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System.Net.Http.Headers; +using Microsoft.Rest; +using Microsoft.Rest.Azure; +using Microsoft.Rest.Serialization; +using Microsoft.Azure.Commands.Websites.Models; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.Websites.Experiments +{ + public partial class CustomWebSiteManagementClient : ServiceClient, IAzureClient + { + /// + /// The base URI of the service. + /// + public System.Uri BaseUri { get; set; } + + /// + /// Gets or sets json serialization settings. + /// + public JsonSerializerSettings SerializationSettings { get; private set; } + + /// + /// Gets or sets json deserialization settings. + /// + public JsonSerializerSettings DeserializationSettings { get; private set; } + + /// + /// Credentials needed for the client to connect to Azure. + /// + public ServiceClientCredentials Credentials { get; private set; } + + /// + /// Your Azure subscription ID. This is a GUID-formatted string (e.g. + /// 00000000-0000-0000-0000-000000000000). + /// + public string SubscriptionId { get; set; } + + /// + /// Gets or sets the preferred language for the response. + /// + public string AcceptLanguage { get; set; } + + /// + /// Gets or sets the retry timeout in seconds for Long Running Operations. + /// Default value is 30. + /// + public int? LongRunningOperationRetryTimeout { get; set; } + + /// + /// When set to true a unique x-ms-client-request-id value is generated and + /// included in each request. Default is true. + /// + public bool? GenerateClientRequestId { get; set; } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected CustomWebSiteManagementClient(params DelegatingHandler[] handlers) : base(handlers) + { + Initialize(); + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected CustomWebSiteManagementClient(HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers) + { + Initialize(); + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + protected CustomWebSiteManagementClient(System.Uri baseUri, params DelegatingHandler[] handlers) : this(handlers) + { + if (baseUri == null) + { + throw new System.ArgumentNullException("baseUri"); + } + BaseUri = baseUri; + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + protected CustomWebSiteManagementClient(System.Uri baseUri, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + if (baseUri == null) + { + throw new System.ArgumentNullException("baseUri"); + } + BaseUri = baseUri; + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Required. Credentials needed for the client to connect to Azure. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + public CustomWebSiteManagementClient(ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers) + { + if (credentials == null) + { + throw new System.ArgumentNullException("credentials"); + } + Credentials = credentials; + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Required. Credentials needed for the client to connect to Azure. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + public CustomWebSiteManagementClient(ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + if (credentials == null) + { + throw new System.ArgumentNullException("credentials"); + } + Credentials = credentials; + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Required. Credentials needed for the client to connect to Azure. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + public CustomWebSiteManagementClient(System.Uri baseUri, ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers) + { + if (baseUri == null) + { + throw new System.ArgumentNullException("baseUri"); + } + if (credentials == null) + { + throw new System.ArgumentNullException("credentials"); + } + BaseUri = baseUri; + Credentials = credentials; + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes a new instance of the CustomWebSiteManagementClient class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Required. Credentials needed for the client to connect to Azure. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + /// + /// Thrown when a required parameter is null + /// + public CustomWebSiteManagementClient(System.Uri baseUri, ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + if (baseUri == null) + { + throw new System.ArgumentNullException("baseUri"); + } + if (credentials == null) + { + throw new System.ArgumentNullException("credentials"); + } + BaseUri = baseUri; + Credentials = credentials; + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes client properties. + /// + private void Initialize() + { + this.HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + BaseUri = new System.Uri("https://management.azure.com"); + AcceptLanguage = "en-US"; + LongRunningOperationRetryTimeout = 30; + GenerateClientRequestId = true; + SerializationSettings = new JsonSerializerSettings + { + Formatting = Newtonsoft.Json.Formatting.Indented, + DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc, + NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore, + ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize, + ContractResolver = new ReadOnlyJsonContractResolver(), + Converters = new System.Collections.Generic.List + { + new Iso8601TimeSpanConverter() + } + }; + SerializationSettings.Converters.Add(new TransformationJsonConverter()); + DeserializationSettings = new JsonSerializerSettings + { + DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc, + NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore, + ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize, + ContractResolver = new ReadOnlyJsonContractResolver(), + Converters = new System.Collections.Generic.List + { + new Iso8601TimeSpanConverter() + } + }; + DeserializationSettings.Converters.Add(new TransformationJsonConverter()); + DeserializationSettings.Converters.Add(new CloudErrorJsonConverter()); + } + + /// + /// Check if a resource name is available. + /// + /// + /// Check if a resource name is available. + /// + /// + /// Resource name to verify. + /// + /// + /// Resource type used for verification. Possible values include: 'Site', + /// 'Slot', 'HostingEnvironment' + /// + /// + /// Is fully qualified domain name. + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// Thrown when the operation returned an invalid status code + /// + /// + /// Thrown when unable to deserialize the response + /// + /// + /// Thrown when a required parameter is null + /// + /// + /// Thrown when a required parameter is null + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> CheckNameAvailabilityWithHttpMessagesAsync(string name, string type, bool? isFqdn = default(bool?), Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)) + { + if (SubscriptionId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "this.SubscriptionId"); + } + if (name == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "name"); + } + if (type == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "type"); + } + string apiVersion = "2016-03-01"; + ResourceNameAvailabilityRequest request = new ResourceNameAvailabilityRequest(); + if (name != null || type != null || isFqdn != null) + { + request.Name = name; + request.Type = type; + request.IsFqdn = isFqdn; + } + // Tracing + bool _shouldTrace = ServiceClientTracing.IsEnabled; + string _invocationId = null; + if (_shouldTrace) + { + _invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary(); + tracingParameters.Add("apiVersion", apiVersion); + tracingParameters.Add("request", request); + tracingParameters.Add("cancellationToken", cancellationToken); + ServiceClientTracing.Enter(_invocationId, this, "CheckNameAvailability", tracingParameters); + } + // Construct URL + var _baseUrl = BaseUri.AbsoluteUri; + var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "subscriptions/{subscriptionId}/providers/Microsoft.Web/checknameavailability").ToString(); + _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(SubscriptionId)); + List _queryParameters = new List(); + if (apiVersion != null) + { + _queryParameters.Add(string.Format("api-version={0}", System.Uri.EscapeDataString(apiVersion))); + } + if (_queryParameters.Count > 0) + { + _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters); + } + // Create HTTP transport objects + var _httpRequest = new System.Net.Http.HttpRequestMessage(); + System.Net.Http.HttpResponseMessage _httpResponse = null; + _httpRequest.Method = new System.Net.Http.HttpMethod("POST"); + _httpRequest.RequestUri = new System.Uri(_url); + // Set Headers + if (GenerateClientRequestId != null && GenerateClientRequestId.Value) + { + _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString()); + } + if (AcceptLanguage != null) + { + if (_httpRequest.Headers.Contains("accept-language")) + { + _httpRequest.Headers.Remove("accept-language"); + } + _httpRequest.Headers.TryAddWithoutValidation("accept-language", AcceptLanguage); + } + if (customHeaders != null) + { + foreach (var _header in customHeaders) + { + if (_httpRequest.Headers.Contains(_header.Key)) + { + _httpRequest.Headers.Remove(_header.Key); + } + _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value); + } + } + + // Serialize Request + string _requestContent = null; + if (request != null) + { + _requestContent = SafeJsonConvert.SerializeObject(request, SerializationSettings); + _httpRequest.Content = new System.Net.Http.StringContent(_requestContent, System.Text.Encoding.UTF8); + _httpRequest.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); + } + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (_shouldTrace) + { + ServiceClientTracing.SendRequest(_invocationId, _httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + _httpResponse = await HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false); + if (_shouldTrace) + { + ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse); + } + HttpStatusCode _statusCode = _httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string _responseContent = null; + if ((int)_statusCode != 200) + { + var ex = new CloudException(string.Format("Operation returned an invalid status code '{0}'", _statusCode)); + try + { + _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + CloudError _errorBody = SafeJsonConvert.DeserializeObject(_responseContent, DeserializationSettings); + if (_errorBody != null) + { + ex = new CloudException(_errorBody.Message); + ex.Body = _errorBody; + } + } + catch (JsonException) + { + // Ignore the exception + } + ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent); + ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent); + if (_httpResponse.Headers.Contains("x-ms-request-id")) + { + ex.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); + } + if (_shouldTrace) + { + ServiceClientTracing.Error(_invocationId, ex); + } + _httpRequest.Dispose(); + if (_httpResponse != null) + { + _httpResponse.Dispose(); + } + throw ex; + } + // Create Result + var _result = new AzureOperationResponse(); + _result.Request = _httpRequest; + _result.Response = _httpResponse; + if (_httpResponse.Headers.Contains("x-ms-request-id")) + { + _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); + } + // Deserialize Response + if ((int)_statusCode == 200) + { + _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + _result.Body = SafeJsonConvert.DeserializeObject(_responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + _httpRequest.Dispose(); + if (_httpResponse != null) + { + _httpResponse.Dispose(); + } + throw new SerializationException("Unable to deserialize the response.", _responseContent, ex); + } + } + if (_shouldTrace) + { + ServiceClientTracing.Exit(_invocationId, _result); + } + return _result; + } + } +} diff --git a/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.csproj b/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.csproj new file mode 100644 index 000000000000..482598f98dd9 --- /dev/null +++ b/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.csproj @@ -0,0 +1,79 @@ + + + + + Debug + AnyCPU + {870244A0-0703-4D43-AF20-58E9F2C6C63E} + Library + Properties + Microsoft.Azure.Commands.Websites.Experiments + Microsoft.Azure.Commands.Websites.Experiments + v4.5.2 + 512 + + + true + full + false + ..\..\src\Package\Debug\ResourceManager\AzureResourceManager\AzureRM.Websites.Experiments\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + packages\Microsoft.Rest.ClientRuntime.2.3.9\lib\net452\Microsoft.Rest.ClientRuntime.dll + + + packages\Microsoft.Rest.ClientRuntime.Azure.3.3.9\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll + + + packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.sln b/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.sln new file mode 100644 index 000000000000..1889858987ce --- /dev/null +++ b/experiments/Websites.Experiments/Microsoft.Azure.Commands.Websites.Experiments.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.6 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Commands.Websites.Experiments", "Microsoft.Azure.Commands.Websites.Experiments.csproj", "{870244A0-0703-4D43-AF20-58E9F2C6C63E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {870244A0-0703-4D43-AF20-58E9F2C6C63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {870244A0-0703-4D43-AF20-58E9F2C6C63E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {870244A0-0703-4D43-AF20-58E9F2C6C63E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {870244A0-0703-4D43-AF20-58E9F2C6C63E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/experiments/Websites.Experiments/Models/ResourceNameAvailability.cs b/experiments/Websites.Experiments/Models/ResourceNameAvailability.cs new file mode 100644 index 000000000000..d32860c63a0f --- /dev/null +++ b/experiments/Websites.Experiments/Models/ResourceNameAvailability.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.Websites.Models +{ + /// + /// Information regarding availbility of a resource name. + /// + public partial class ResourceNameAvailability + { + /// + /// Initializes a new instance of the ResourceNameAvailability class. + /// + public ResourceNameAvailability() { } + + /// + /// Initializes a new instance of the ResourceNameAvailability class. + /// + /// <code>true</code> indicates + /// name is valid and available. <code>false</code> + /// indicates the name is invalid, unavailable, or both. + /// <code>Invalid</code> indicates the + /// name provided does not match Azure App Service naming requirements. + /// <code>AlreadyExists</code> indicates that the name is + /// already in use and is therefore unavailable. Possible values + /// include: 'Invalid', 'AlreadyExists' + /// If reason == invalid, provide the user with + /// the reason why the given name is invalid, and provide the resource + /// naming requirements so that the user can select a valid name. If + /// reason == AlreadyExists, explain that resource name is already in + /// use, and direct them to select a different name. + public ResourceNameAvailability(bool? nameAvailable = default(bool?), string reason = default(string), string message = default(string)) + { + NameAvailable = nameAvailable; + Reason = reason; + Message = message; + } + + /// + /// Gets or sets &lt;code&gt;true&lt;/code&gt; + /// indicates name is valid and available. + /// &lt;code&gt;false&lt;/code&gt; indicates the name + /// is invalid, unavailable, or both. + /// + [JsonProperty(PropertyName = "nameAvailable")] + public bool? NameAvailable { get; set; } + + /// + /// Gets or sets &lt;code&gt;Invalid&lt;/code&gt; + /// indicates the name provided does not match Azure App Service naming + /// requirements. + /// &lt;code&gt;AlreadyExists&lt;/code&gt; indicates + /// that the name is already in use and is therefore unavailable. + /// Possible values include: 'Invalid', 'AlreadyExists' + /// + [JsonProperty(PropertyName = "reason")] + public string Reason { get; set; } + + /// + /// Gets or sets if reason == invalid, provide the user with the reason + /// why the given name is invalid, and provide the resource naming + /// requirements so that the user can select a valid name. If reason == + /// AlreadyExists, explain that resource name is already in use, and + /// direct them to select a different name. + /// + [JsonProperty(PropertyName = "message")] + public string Message { get; set; } + + } +} + diff --git a/experiments/Websites.Experiments/Models/ResourceNameAvailabilityRequest.cs b/experiments/Websites.Experiments/Models/ResourceNameAvailabilityRequest.cs new file mode 100644 index 000000000000..e8815bcd0ffb --- /dev/null +++ b/experiments/Websites.Experiments/Models/ResourceNameAvailabilityRequest.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Microsoft.Rest; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.Websites.Models +{ + /// + /// Resource name availability request content. + /// + public partial class ResourceNameAvailabilityRequest + { + /// + /// Initializes a new instance of the ResourceNameAvailabilityRequest + /// class. + /// + public ResourceNameAvailabilityRequest() { } + + /// + /// Initializes a new instance of the ResourceNameAvailabilityRequest + /// class. + /// + /// Resource name to verify. + /// Resource type used for verification. Possible + /// values include: 'Site', 'Slot', 'HostingEnvironment' + /// Is fully qualified domain name. + public ResourceNameAvailabilityRequest(string name, string type, bool? isFqdn = default(bool?)) + { + Name = name; + Type = type; + IsFqdn = isFqdn; + } + + /// + /// Gets or sets resource name to verify. + /// + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + + /// + /// Gets or sets resource type used for verification. Possible values + /// include: 'Site', 'Slot', 'HostingEnvironment' + /// + [JsonProperty(PropertyName = "type")] + public string Type { get; set; } + + /// + /// Gets or sets is fully qualified domain name. + /// + [JsonProperty(PropertyName = "isFqdn")] + public bool? IsFqdn { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (Name == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Name"); + } + if (Type == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Type"); + } + } + } +} + diff --git a/experiments/Websites.Experiments/Properties/AssemblyInfo.cs b/experiments/Websites.Experiments/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..fc401feae3db --- /dev/null +++ b/experiments/Websites.Experiments/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.Azure.Commands.Websites.Experiments")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.Azure.Commands.Websites.Experiments")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("870244a0-0703-4d43-af20-58e9f2c6c63e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/experiments/Websites.Experiments/Run-UnitTests.ps1 b/experiments/Websites.Experiments/Run-UnitTests.ps1 new file mode 100644 index 000000000000..68debcdb8413 --- /dev/null +++ b/experiments/Websites.Experiments/Run-UnitTests.ps1 @@ -0,0 +1,5 @@ +#Requires -Modules AzureRM.Websites.Experiments, Pester + +$defaults = [System.IO.Path]::GetDirectoryName($PSCommandPath) +Set-Location $defaults +Invoke-Pester -EnableExit \ No newline at end of file diff --git a/experiments/Websites.Experiments/help/New-AzWebApp.md b/experiments/Websites.Experiments/help/New-AzWebApp.md new file mode 100644 index 000000000000..947b3d077a27 --- /dev/null +++ b/experiments/Websites.Experiments/help/New-AzWebApp.md @@ -0,0 +1,136 @@ +--- +external help file: AzureRM.Websites.Experiments-help.xml +online version: +schema: 2.0.0 +--- + +# New-AzWebApp + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +New-AzWebApp [[-WebAppName] ] [[-ResourceGroupName] ] [[-AppServicePlan] ] [-Auto] + [-AddRemote] [[-GitRepositoryPath] ] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +``` +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -AddRemote +{{Fill AddRemote Description}} + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AppServicePlan +{{Fill AppServicePlan Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Plan + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Auto +{{Fill Auto Description}} + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GitRepositoryPath +{{Fill GitRepositoryPath Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +{{Fill ResourceGroupName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Group + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebAppName +{{Fill WebAppName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Name + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + + +## OUTPUTS + +### Microsoft.Azure.Management.WebSites.Models.Site + + +## NOTES + +## RELATED LINKS + diff --git a/experiments/Websites.Experiments/help/New-AzWebAppGrayParam.md b/experiments/Websites.Experiments/help/New-AzWebAppGrayParam.md new file mode 100644 index 000000000000..6a192810cb08 --- /dev/null +++ b/experiments/Websites.Experiments/help/New-AzWebAppGrayParam.md @@ -0,0 +1,136 @@ +--- +external help file: AzureRM.Websites.Experiments-help.xml +online version: +schema: 2.0.0 +--- + +# New-AzWebAppGrayParam + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +New-AzWebAppGrayParam [[-WebAppName] ] [[-ResourceGroupName] ] [[-AppServicePlan] ] + [-Auto] [-AddRemote] [[-GitRepositoryPath] ] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +``` +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -AddRemote +{{Fill AddRemote Description}} + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AppServicePlan +{{Fill AppServicePlan Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Plan + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Auto +{{Fill Auto Description}} + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GitRepositoryPath +{{Fill GitRepositoryPath Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +{{Fill ResourceGroupName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Group + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebAppName +{{Fill WebAppName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Name + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + + +## OUTPUTS + +### Microsoft.Azure.Management.WebSites.Models.Site + + +## NOTES + +## RELATED LINKS + diff --git a/experiments/Websites.Experiments/help/New-AzWebAppJustDoIt.md b/experiments/Websites.Experiments/help/New-AzWebAppJustDoIt.md new file mode 100644 index 000000000000..d561e01cf596 --- /dev/null +++ b/experiments/Websites.Experiments/help/New-AzWebAppJustDoIt.md @@ -0,0 +1,90 @@ +--- +external help file: AzureRM.Websites.Experiments-help.xml +online version: +schema: 2.0.0 +--- + +# New-AzWebAppJustDoIt + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +New-AzWebAppJustDoIt [[-WebAppName] ] [[-ResourceGroupName] ] [[-AppServicePlan] ] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +``` +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -AppServicePlan +{{Fill AppServicePlan Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Plan + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +{{Fill ResourceGroupName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Group + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebAppName +{{Fill WebAppName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: Name + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + + +## OUTPUTS + +### Microsoft.Azure.Management.WebSites.Models.Site + + +## NOTES + +## RELATED LINKS + diff --git a/experiments/Websites.Experiments/packages.config b/experiments/Websites.Experiments/packages.config new file mode 100644 index 000000000000..d0a5c6543553 --- /dev/null +++ b/experiments/Websites.Experiments/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs b/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs index 75f3b2e9960b..f47ecac59713 100644 --- a/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs +++ b/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs @@ -168,6 +168,8 @@ private void AnalyzeMarkdownHelp( HelpFile = service + "/folder", ProblemId = MissingHelpFile }); + + return; } var helpFiles = Directory.EnumerateFiles(helpFolder, "*.md").Select(f => Path.GetFileNameWithoutExtension(f)).ToList(); @@ -194,6 +196,10 @@ private void AnalyzeMarkdownHelp( " -FileName " + psd1FileName + " -BindingVariable ModuleMetadata; $ModuleMetadata.NestedModules"); var cmdletResult = powershell.Invoke(); + if (string.IsNullOrEmpty(cmdletResult.ToString())) + { + return; + } var cmdletFiles = cmdletResult.Select(c => c.ToString().Substring(2)); if (cmdletFiles.Any()) {