Skip to content

Commit

Permalink
Merge pull request #356 from alexdrenea/feature/ef-migrations
Browse files Browse the repository at this point in the history
Feature/ef migrations
  • Loading branch information
santhoshb-msft authored Dec 1, 2022
2 parents f57ff86 + 225b342 commit b97dcac
Show file tree
Hide file tree
Showing 20 changed files with 6,332 additions and 1,504 deletions.
1,409 changes: 0 additions & 1,409 deletions deployment/Database/AMP-DB.sql

This file was deleted.

Binary file removed deployment/Database/AMPSaaSDB.bacpac
Binary file not shown.
72 changes: 39 additions & 33 deletions deployment/Templates/Deploy.ps1 → deployment/Deploy.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ Param(
[string][Parameter()]$ADApplicationID, # The value should match the value provided for Active Directory Application ID in the Technical Configuration of the Transactable Offer in Partner Center
[string][Parameter()]$ADApplicationSecret, # Secret key of the AD Application
[string][Parameter()]$ADMTApplicationID, # The value should match the value provided for Multi-Tenant Active Directory Application ID in the Technical Configuration of the Transactable Offer in Partner Center
[string][Parameter(Mandatory)]$SQLServerName, # Name of the database server (without database.windows.net)
[string][Parameter(Mandatory)]$SQLAdminLogin, # SQL Admin login
[string][Parameter(Mandatory)]$SQLAdminLoginPassword, # SQL Admin password
[string][Parameter()]$SQLDatabaseName, # Name of the database (Defaults to AMPSaaSDB)
[string][Parameter()]$SQLServerName, # Name of the database server (without database.windows.net)
[string][Parameter()]$SQLAdminLogin, # SQL Admin login
[string][Parameter()]$SQLAdminLoginPassword, # SQL Admin password
[string][Parameter(Mandatory)]$PublisherAdminUsers, # Provide a list of email addresses (as comma-separated-values) that should be granted access to the Publisher Portal
[string][Parameter(Mandatory)]$ResourceGroupForDeployment, # Name of the resource group to deploy the resources
[string][Parameter(Mandatory)]$Location, # Location of the resource group
Expand All @@ -25,6 +26,20 @@ Param(

$ErrorActionPreference = "Stop"
$SaaSApiConfiguration_CodeHash= git log --format='%H' -1
#Setting up default Sql Parameters
if ($SQLServerName -eq "") {
$SQLServerName = $WebAppNamePrefix + "-sql"
}
if ($SQLAdminLogin -eq "") {
$SQLAdminLogin = "saasdbadmin" + $(Get-Random -Minimum 1 -Maximum 1000)
}
if ($SQLAdminLoginPassword -eq "") {
$SQLAdminLoginPassword = ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((New-Guid))))+"="
}
if($SQLDatabaseName -eq "") {
$SQLDatabaseName = "AMPSaaSDB"
}

# Checking SQL username
if($SQLAdminLogin.ToLower() -eq "admin") {
Throw "🛑 SQLAdminLogin may not be 'admin'."
Expand Down Expand Up @@ -188,36 +203,35 @@ if($LogoURLico) {
Write-Host "📷 Logo images ICO downloaded."
}

Write-host "☁ Prepare publish files faS.Accelerator.or the web application"
Write-host "☁ Prepare publish files for the web application"

Write-host "☁ Preparing the publish files for Admin Site"
dotnet publish ..\..\src\AdminSite\AdminSite.csproj -c debug -o ..\..\Publish\AdminSite\

dotnet publish ../src/AdminSite/AdminSite.csproj -v q -c debug -o ../Publish/AdminSite/

Write-host "☁ Preparing the publish files for Metered Scheduler to Admin Site"
mkdir -p ..\..\Publish\AdminSite\app_data\jobs\triggered\MeteredTriggerJob
dotnet publish ..\..\src\MeteredTriggerJob\MeteredTriggerJob.csproj -c debug -o ..\..\Publish\AdminSite\app_data\jobs\triggered\MeteredTriggerJob --runtime win-x64 --self-contained true
dotnet publish ../src/MeteredTriggerJob/MeteredTriggerJob.csproj -v q -c debug -o ../Publish/AdminSite/app_data/jobs/triggered/MeteredTriggerJob --runtime win-x64 --self-contained true

Compress-Archive -Path ..\..\Publish\AdminSite\* -DestinationPath ..\..\Publish\AdminSite.zip -Force
Compress-Archive -Path ../Publish/AdminSite/* -DestinationPath ../Publish/AdminSite.zip -Force

Write-host "☁ Preparing the publish files for Customer Site"
dotnet publish ..\..\src\CustomerSite\CustomerSite.csproj -c debug -o ..\..\Publish\CustomerSite
Compress-Archive -Path ..\..\Publish\CustomerSite\* -DestinationPath ..\..\Publish\CustomerSite.zip -Force
dotnet publish ../src/CustomerSite/CustomerSite.csproj -v q -c debug -o ../Publish/CustomerSite
Compress-Archive -Path ../Publish/CustomerSite/* -DestinationPath ../Publish/CustomerSite.zip -Force

Write-host "☁ Path to web application packages $PathToWebApplicationPackages"

# Create RG if not exists
az group create --location $location --name $ResourceGroupForDeployment

Write-host "📜 Start Deploy resources"
$WebAppNameService=$WebAppNamePrefix+"AmpSvcPlan"
$WebAppNameService=$WebAppNamePrefix+"-asp"
$WebAppNameAdmin=$WebAppNamePrefix+"-admin"
$WebAppNamePortal=$WebAppNamePrefix+"-portal"
$KeyVault=$WebAppNamePrefix+"-kv"
$KeyVault=$KeyVault -replace '_',''
$ADApplicationSecretKeyVault='"@Microsoft.KeyVault(VaultName={0};SecretName=ADApplicationSecret)"' -f $KeyVault
$DefaultConnectionKeyVault='"@Microsoft.KeyVault(VaultName={0};SecretName=DefaultConnection)"' -f $KeyVault
$Connection="Data Source=tcp:"+$SQLServerName+".database.windows.net,1433;Initial Catalog=AMPSaaSDB;User Id="+$SQLAdminLogin+"@"+$SQLServerName+".database.windows.net;Password="+$SQLAdminLoginPassword+";"
$ServerUri = $SQLServerName+".database.windows.net"
$Connection="Data Source=tcp:"+$ServerUri+",1433;Initial Catalog=AMPSaaSDB;User Id="+$SQLAdminLogin+"@"+$SQLServerName+".database.windows.net;Password="+$SQLAdminLoginPassword+";"

Write-host "Create SQL Server"
az sql server create --name $SQLServerName --resource-group $ResourceGroupForDeployment --location "$location" --admin-user $SQLAdminLogin --admin-password $SQLAdminLoginPassword
Expand All @@ -228,24 +242,17 @@ az sql server firewall-rule create --resource-group $ResourceGroupForDeployment
Write-host "Create SQL DB"
az sql db create --resource-group $ResourceGroupForDeployment --server $SQLServerName --name "AMPSaaSDB" --edition Standard --capacity 10 --zone-redundant false

## Prepare to deploy packages
## This step to solve Linux/Windows relative path issue
if ($IsLinux)
{
$dbSqlFile=(get-item . ).parent.FullName+"/Database/AMP-DB.sql"
$publisherPackage=(get-item . ).parent.parent.FullName+"/Publish/AdminSite.zip"
$customerPackage=(get-item . ).parent.parent.FullName+"/Publish/CustomerSite.zip"
}
else {
$dbSqlFile=(get-item . ).parent.FullName+"\Database\AMP-DB.sql"
$publisherPackage=(get-item . ).parent.parent.FullName+"\Publish\AdminSite.zip"
$customerPackage=(get-item . ).parent.parent.FullName+"\Publish\CustomerSite.zip"
}
Write-host "Generate SQL schema/data script"

Set-Content -Path ../src/AdminSite/appsettings.Development.json -value "{`"ConnectionStrings`": {`"DefaultConnection`":`"$Connection`"}}"
dotnet-ef migrations script --output script.sql --idempotent --context SaaSKitContext --project ../src/DataAccess/DataAccess.csproj --startup-project ../src/AdminSite/AdminSite.csproj

# Deploy Code and database schema
Write-host "📜 Deploying the database schema"
$ServerUri = $SQLServerName+".database.windows.net"
Invoke-Sqlcmd -ServerInstance $ServerUri -database "AMPSaaSDB" -Username $SQLAdminLogin -Password $SQLAdminLoginPassword -InputFile $dbSqlFile
Invoke-Sqlcmd -InputFile ./script.sql -ServerInstance $ServerUri -database $SQLDatabaseName -Username $SQLAdminLogin -Password $SQLAdminLoginPassword

Remove-Item -Path ../src/AdminSite/appsettings.Development.json
Remove-Item -Path script.sql


Write-host "📜 Create Keyvault"
az keyvault create --name $KeyVault --resource-group $ResourceGroupForDeployment
Expand Down Expand Up @@ -283,14 +290,13 @@ az webapp config connection-string set -g $ResourceGroupForDeployment -n $WebApp
az webapp config appsettings set -g $ResourceGroupForDeployment -n $WebAppNamePortal --settings KnownUsers=$PublisherAdminUsers SaaSApiConfiguration__AdAuthenticationEndPoint=https://login.microsoftonline.com SaaSApiConfiguration__ClientId=$ADApplicationID SaaSApiConfiguration__ClientSecret=$ADApplicationSecretKeyVault SaaSApiConfiguration__FulFillmentAPIBaseURL=https://marketplaceapi.microsoft.com/api SaaSApiConfiguration__FulFillmentAPIVersion=2018-08-31 SaaSApiConfiguration__GrantType=client_credentials SaaSApiConfiguration__MTClientId=$ADMTApplicationID SaaSApiConfiguration__Resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7 SaaSApiConfiguration__TenantId=$TenantID SaaSApiConfiguration__SignedOutRedirectUri=https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/ SaaSApiConfiguration__SupportmeteredBilling=$MeteredSchedulerSupport SaaSApiConfiguration_CodeHash=$SaaSApiConfiguration_CodeHash

Write-host "📜 Deploying the Publisher Code to Admin Site"
az webapp deploy --resource-group "$ResourceGroupForDeployment" --name "$WebAppNameAdmin" --src-path $publisherPackage --type zip

az webapp deploy --resource-group $ResourceGroupForDeployment --name $WebAppNameAdmin --src-path "../Publish/AdminSite.zip" --type zip
Write-host "📜 Deploying the Customer Code to Customer Site"
az webapp deploy --resource-group "$ResourceGroupForDeployment" --name "$WebAppNamePortal" --src-path $customerPackage --type zip
az webapp deploy --resource-group $ResourceGroupForDeployment --name $WebAppNamePortal --src-path "../Publish/CustomerSite.zip" --type zip

Write-host "🧹 Cleaning things up!"
# Cleanup : Delete the temporary storage account and the resource group created to host the bacpac file.
Remove-Item -path ["..\..\Publish"] -recurse -Force
Remove-Item -Path ../Publish -recurse -Force

Write-host "🏁 If the intallation completed without error complete the folllowing checklist:"

Expand Down
6 changes: 3 additions & 3 deletions deployment/Database/README.md → deployment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ The customer portal and the publisher portal sample web applications use SQL Ser

## Install Using SQL Scripts

The SQL scripts build on top of each other. When setting up your database, do the following.
The project uses EntityFramework Core Code-First approach to the database design and maintainance.
When deploying a new version of the accelerator the `dotnet-ef` tool is used to generate a migration script from your current database state to the latest state. All necesary changes will be automatically applied during deployment

1. Start with a blank database
2. Run AMP-DB-2.1.sql
When installing the accelerator for the first time, a fresh db creation script is auto-generated based on the latest version of the code and automatically creates the db schema and seeds the initial data required for operation.

## Description

Expand Down
123 changes: 123 additions & 0 deletions deployment/Upgrade.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE file in the project root for license information.

#
# Powershell script to deploy the resources - Customer portal, Publisher portal and the Azure SQL Database
#

Param(
[string][Parameter(Mandatory)]$WebAppNamePrefix, # Prefix used for creating web applications
[string][Parameter(Mandatory)]$ResourceGroupForDeployment # Name of the resource group to deploy the resources
)

Function String-Between
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][String]$Source,
[Parameter(Mandatory=$true)][String]$Start,
[Parameter(Mandatory=$true)][String]$End
)
$sIndex = $Source.indexOf($Start) + $Start.length
$eIndex = $Source.indexOf($End, $sIndex)
return $Source.Substring($sIndex, $eIndex-$sIndex)
}

$ErrorActionPreference = "Stop"
$WebAppNameAdmin=$WebAppNamePrefix+"-admin"
$WebAppNamePortal=$WebAppNamePrefix+"-portal"
$KeyVault=$WebAppNamePrefix+"-kv"

#### THIS SECTION DEPLOYS CODE AND DATABASE CHANGES
Write-host "#### Deploying new database ####"
$ConnectionString = az keyvault secret show `
--vault-name $KeyVault `
--name "DefaultConnection" `
--query "{value:value}" `
--output tsv

#Extract components from ConnectionString since Invoke-Sqlcmd needs them separately
$Server = String-Between -source $ConnectionString -start "Data Source=" -end ";"
$Database = String-Between -source $ConnectionString -start "Initial Catalog=" -end ";"
$User = String-Between -source $ConnectionString -start "User Id=" -end ";"
$Pass = String-Between -source $ConnectionString -start "Password=" -end ";"

Write-host "## Retrieved ConnectionString from KeyVault"
Set-Content -Path ../src/AdminSite/appsettings.Development.json -value "{`"ConnectionStrings`": {`"DefaultConnection`":`"$ConnectionString`"}}"

dotnet-ef migrations script `
--idempotent `
--context SaaSKitContext `
--project ../src/DataAccess/DataAccess.csproj `
--startup-project ../src/AdminSite/AdminSite.csproj `
--output script.sql

Write-host "## Generated migration script"

Write-host "## !!!Attempting to upgrade database to migration compatibility.!!!"
$compatibilityScript = "
IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
-- No __EFMigrations table means Database has not been upgraded to support EF Migrations
BEGIN
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
IF (SELECT TOP 1 VersionNumber FROM DatabaseVersionHistory ORDER BY CreateBy DESC) = '2.10'
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20221118045814_Baseline_v2', N'6.0.1');
IF (SELECT TOP 1 VersionNumber FROM DatabaseVersionHistory ORDER BY CreateBy DESC) = '5.00'
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20221118045814_Baseline_v2', N'6.0.1'), (N'20221118203340_Baseline_v5', N'6.0.1');
IF (SELECT TOP 1 VersionNumber FROM DatabaseVersionHistory ORDER BY CreateBy DESC) = '6.10'
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20221118045814_Baseline_v2', N'6.0.1'), (N'20221118203340_Baseline_v5', N'6.0.1'), (N'20221118211554_Baseline_v6', N'6.0.1');
END;
GO"

Invoke-Sqlcmd -query $compatibilityScript -ServerInstance $Server -database $Database -Username $User -Password $Pass
Write-host "## Ran compatibility script against database"
Invoke-Sqlcmd -inputFile script.sql -ServerInstance $Server -database $Database -Username $User -Password $Pass
Write-host "## Ran migration against database"

Remove-Item -Path ../src/AdminSite/appsettings.Development.json
Remove-Item -Path script.sql
Write-host "#### Database Deployment complete ####"



Write-host "#### Deploying new code ####"

dotnet publish ../src/AdminSite/AdminSite.csproj -v q -c debug -o ../Publish/AdminSite/
Write-host "## Admin Portal built"
dotnet publish ../src/MeteredTriggerJob/MeteredTriggerJob.csproj -v q -c debug -o ../Publish/AdminSite/app_data/jobs/triggered/MeteredTriggerJob --runtime win-x64 --self-contained true
Write-host "## Metered Scheduler to Admin Portal Built"
dotnet publish ../src/CustomerSite/CustomerSite.csproj -v q -c debug -o ../Publish/CustomerSite
Write-host "## Customer Portal Built"

Compress-Archive -Path ../Publish/CustomerSite/* -DestinationPath ../Publish/CustomerSite.zip -Force
Compress-Archive -Path ../Publish/AdminSite/* -DestinationPath ../Publish/AdminSite.zip -Force
Write-host "## Code packages prepared."

Write-host "## Deploying code to Admin Portal"
az webapp deploy `
--resource-group $ResourceGroupForDeployment `
--name $WebAppNameAdmin `
--src-path "../Publish/AdminSite.zip" `
--type zip
Write-host "## Deployed code to Admin Portal"

Write-host "## Deploying code to Customer Portal"
az webapp deploy `
--resource-group $ResourceGroupForDeployment `
--name $WebAppNamePortal `
--src-path "../Publish/CustomerSite.zip" `
--type zip
Write-host "## Deployed code to Customer Portal"

Remove-Item -Path ../Publish -recurse -Force
Write-host "#### Code deployment complete ####"
34 changes: 29 additions & 5 deletions docs/Installation-Instructions.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
## Install the Azure Marketplace SaaS Accelerator using Azure Cloud Shell

You can install the SaaS Accelerator code using a __single command__ line within the Azure Portal ([video tutorial](https://youtu.be/BVZTj6fssQ8)).

1. Copy the following section to an editor and update it to match your company preference. Replace `SOME-UNIQUE-STRING` with your Team name or some other random string.

1. Copy the following section to an editor and update it to match your company preference.
- Replace `SOME-UNIQUE-STRING` with your Team name or some other meaningful name for your depth. (Ensure that the final name does not exceed 24 characters)
- Replace `[email protected]` with a valid email from your org that will use the portal for the first time. Once deployed, this account will be able to login to the administration panel and give access to more users.
- [optional] Replace `MarketplaceSaasGitHub` under `ResourceGroupForDeployment` with a value that matches your comany's naming conventions for resource groups
- [optional] Replace `East US` with a region closest to you.

``` powershell
dotnet tool install --global dotnet-ef; `
git clone https://github.com/Azure/Commercial-Marketplace-SaaS-Accelerator.git -b 6.0.1 --depth 1; `
cd ./Commercial-Marketplace-SaaS-Accelerator/deployment/Templates; `
cd ./Commercial-Marketplace-SaaS-Accelerator/deployment; `
Connect-AzureAD -Confirm; `
.\Deploy.ps1 `
-WebAppNamePrefix "marketplace-SOME-UNIQUE-STRING" `
Expand All @@ -15,7 +20,7 @@ Connect-AzureAD -Confirm; `
-SQLAdminLoginPassword "" `
-PublisherAdminUsers "[email protected]" `
-ResourceGroupForDeployment "MarketplaceSaasGitHub" `
-Location "East US"
-Location "East US"; `
```

The following lines are optional:
Expand All @@ -28,7 +33,25 @@ Connect-AzureAD -Confirm; `
-LogoURLpng "https://company_com/company_logo.png" `
-LogoURLico "https://company_com/company_logo.ico"
```

The scripts above will perform these actions:
- Create required App Registration for SaaS Marketplace API authentication
- Create APP registration for SSO on your Landing Page
- Deploy required infrastructure in Azure for

## Update to a newer version of the SaaS Accelerator

If you are already have deployed the SaaS Accelerator, but you want to update it so that you take advantage of new features developed, you can run the following command.

*you need to ensure that you use the same parameters you used in the initial deployment

``` powershell
git clone https://github.com/Azure/Commercial-Marketplace-SaaS-Accelerator.git -b <branch-to-deploy> --depth 1; `
cd ./Commercial-Marketplace-SaaS-Accelerator/deployment; `
.\Upgrade.ps1 `
-WebAppNamePrefix "marketplace-SOME-UNIQUE-STRING" `
-ResourceGroupForDeployment "MarketplaceSaasGitHub" `
```

## Parameters

| Parameter | Description |
Expand All @@ -48,5 +71,6 @@ Connect-AzureAD -Confirm; `
| LogoURLpng | The url of the company logo image in .png format with a size of 96x96 to be used on the website |
| LogoURLico | The url of the company logo image in .ico format |
| MeteredSchedulerSupport | Enable the metered scheduler. This is deployed by default. Use **true** to enable the feature. More information [here](https://github.com/Azure/Commercial-Marketplace-SaaS-Accelerator/blob/main/docs/Metered-Scheduler-Manager-Instruction.md).

## Alternative Deployments
There are other ways to deploy the SaaS Accelerator environment (e.g. development, maual deployment, etc). Additional instruction can be found [here](Advanced-Instructions.md).
Loading

0 comments on commit b97dcac

Please sign in to comment.