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 <code>true</code>
+ /// indicates name is valid and available.
+ /// <code>false</code> indicates the name
+ /// is invalid, unavailable, or both.
+ ///
+ [JsonProperty(PropertyName = "nameAvailable")]
+ public bool? NameAvailable { get; set; }
+
+ ///
+ /// Gets or sets <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'
+ ///
+ [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())
{