Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 61 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,38 @@ The service was developed primary for syncing on premise SQL server data to Azur

## Prerequisites

- .NET 7 SDK - https://dotnet.microsoft.com/en-us/download
- Azure Functions Core Tools version 4.0.4785, or a later version. - https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#v2
- Azure CLI version 2.20, or a later version. - https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
- .NET 10 SDK - https://dotnet.microsoft.com/en-us/download
- Azure Functions Core Tools version 4.0, or a later version - https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#v2
- Azure CLI version 2.50, or a later version - https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
- IDE
- Visual Studio - 17.4.2, or a later version
- VS Code - 1.73.1, or a later version
- Visual Studio 2022 17.10, or a later version
- VS Code 1.90, or a later version

## Configuration

The function is configured through Azure App Settings / Environment variables, you can have multiple sync source/targets configures, and multiple tables per sync job.

| Key | Description | Example |
|-----------------------------------------------------|-------------------------------------------|------------------------------------------------------------------------------|
| `ProcessGlobalChangeTrackingSchedule` | Custom schedule cron expression | `0 */5 * * * *` |
| `SyncJobsConfig:Jobs:[key]:Source:ConnectionString` | Source database connection string | `Server=my.dbserver.net;Initial Catalog=MySourceDb;Integrated Security=True` |
| `SyncJobsConfig:Jobs:[key]:Source:ManagedIdentity` | Flag for if managed identity used | `false` |
| `SyncJobsConfig:Jobs:[key]:Source:TenantId` | Azure tenant ID used for managed identity | `46b41530-1e0d-4403-b815-24815944aa6a` |
| `SyncJobsConfig:Jobs:[key]:Target:ConnectionString` | Target database connection string | `Server=my.dbserver.net;Initial Catalog=MyTargetDb;Integrated Security=True` |
| `SyncJobsConfig:Jobs:[key]:Target:ManagedIdentity` | Flag for if managed identity used | `true` |
| `SyncJobsConfig:Jobs:[key]:Target:TenantId` | Azure tenant ID used for managed identity | `46b41530-1e0d-4403-b815-24815944aa6a` |
| `SyncJobsConfig:Jobs:[key]:BatchSize` | Bulk sync batch size | `1000` |
| `SyncJobsConfig:Jobs:[key]:Area` | Area name, used to manually trigger sync | `Development` |
| `SyncJobsConfig:Jobs:[key]:Manual` | Flag is sync excluded from schedules | `true` |
| `SyncJobsConfig:Jobs:[key]:Schedules:[key]` | Optional opt-in/out schedules | `true` |
| `SyncJobsConfig:Jobs:[key]:Tables:[key]` | Fully qualified name of table to sync | `dbo.MyTable` |
| Key | Description | Example |
|---------------------------------------------------------------------|-------------------------------------------|------------------------------------------------------------------------------|
| `ProcessGlobalChangeTrackingSchedule` | Custom schedule cron expression | `0 */5 * * * *` |
| `SyncJobsConfig__Jobs__[key]__Source__ConnectionString` | Source database connection string | `Server=my.dbserver.net;Initial Catalog=MySourceDb;Integrated Security=True` |
| `SyncJobsConfig__Jobs__[key]__Source__ManagedIdentity` | Flag for if managed identity used | `false` |
| `SyncJobsConfig__Jobs__[key]__Source__TenantId` | Azure tenant ID used for managed identity | `46b41530-1e0d-4403-b815-24815944aa6a` |
| `SyncJobsConfig__Jobs__[key]__Target__ConnectionString` | Target database connection string | `Server=my.dbserver.net;Initial Catalog=MyTargetDb;Integrated Security=True` |
| `SyncJobsConfig__Jobs__[key]__Target__ManagedIdentity` | Flag for if managed identity used | `true` |
| `SyncJobsConfig__Jobs__[key]__Target__TenantId` | Azure tenant ID used for managed identity | `46b41530-1e0d-4403-b815-24815944aa6a` |
| `SyncJobsConfig__Jobs__[key]__BatchSize` | Bulk sync batch size | `1000` |
| `SyncJobsConfig__Jobs__[key]__Area` | Area name, used to manually trigger sync | `Development` |
| `SyncJobsConfig__Jobs__[key]__Manual` | Flag is sync excluded from schedules | `true` |
| `SyncJobsConfig__Jobs__[key]__Schedules__[key]` | Optional opt-in/out schedules | `true` |
| `SyncJobsConfig__Jobs__[key]__Tables__[key]` | Fully qualified name of table to sync | `dbo.MyTable` |


> Note:
>
> Replace `[key]` with unique name of sync job / table config i.e. `MySync` / `MyTable` would result in `SyncJobsConfig:Jobs:MySync:Tables:MyTable`=`dbo.MyTable`
> Replace `[key]` with unique name of sync job / table config i.e. `MySync` / `MyTable` would result in `SyncJobsConfig__Jobs__MySync__Tables__MyTable`=`dbo.MyTable`
>
> Non-Windows operating systems you'll need to replace `:` with `__`, i.e. `SyncJobsConfig__Jobs__MySync__Tables__MyTable`
>
> Configuration from KeyVault replace `:` with `--` i.e. `SyncJobsConfig--Jobs--MySync--Tables--MyTable`
> Configuration from KeyVault replace `__` with `--` i.e. `SyncJobsConfig--Jobs--MySync--Tables--MyTable`

## Schedules

Expand Down Expand Up @@ -71,24 +69,50 @@ To quicker get started testing the function locally example configuration and da
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"ProcessGlobalChangeTrackingSchedule": "0 23 11 * * *",
"SyncJobsConfig:Jobs:SyncTest:Area": "SyncTest",
"SyncJobsConfig:Jobs:SyncTest:Source:ConnectionString": "Server=localhost;Initial Catalog=SyncTest;Integrated Security=True",
"SyncJobsConfig:Jobs:SyncTest:Source:ManagedIdentity": false,
"SyncJobsConfig:Jobs:SyncTest:Target:ConnectionString": "Server=localhost;Initial Catalog=SyncTest;Integrated Security=True",
"SyncJobsConfig:Jobs:SyncTest:Target:ManagedIdentity": false,
"SyncJobsConfig:Jobs:SyncTest:BatchSize": 1000,
"SyncJobsConfig:Jobs:SyncTest:Manual": false,
"SyncJobsConfig:Jobs:SyncTest:Tables:Test": "source.[Test]",
"SyncJobsConfig:Jobs:SyncTest:TargetTables:Test": "target.[Test]",
"SyncJobsConfig:Jobs:SyncTest:Schedules:Custom": true,
"SyncJobsConfig:Jobs:SyncTest:Schedules:Noon": true,
"SyncJobsConfig:Jobs:SyncTest:Schedules:Midnight": true,
"SyncJobsConfig:Jobs:SyncTest:Schedules:EveryFiveMinutes": true,
"SyncJobsConfig:Jobs:SyncTest:Schedules:EveryHour": true
"SyncJobsConfig__Jobs__SyncTest__Area": "SyncTest",
"SyncJobsConfig__Jobs__SyncTest__Source__ConnectionString": "Server=localhost;Initial Catalog=SyncTest;Integrated Security=True",
"SyncJobsConfig__Jobs__SyncTest__Source__ManagedIdentity": false,
"SyncJobsConfig__Jobs__SyncTest__Target__ConnectionString": "Server=localhost;Initial Catalog=SyncTest;Integrated Security=True",
"SyncJobsConfig__Jobs__SyncTest__Target__ManagedIdentity": false,
"SyncJobsConfig__Jobs__SyncTest__BatchSize": 1000,
"SyncJobsConfig__Jobs__SyncTest__Manual": false,
"SyncJobsConfig__Jobs__SyncTest__Tables__Test": "source.[Test]",
"SyncJobsConfig__Jobs__SyncTest__TargetTables__Test": "target.[Test]",
"SyncJobsConfig__Jobs__SyncTest__Schedules__Custom": true,
"SyncJobsConfig__Jobs__SyncTest__Schedules__Noon": true,
"SyncJobsConfig__Jobs__SyncTest__Schedules__Midnight": true,
"SyncJobsConfig__Jobs__SyncTest__Schedules__EveryFiveMinutes": true,
"SyncJobsConfig__Jobs__SyncTest__Schedules__EveryHour": true
}
}
```

### Example .env file for Docker

```
# Environment variables for running SqlBulkSyncFunction in Docker

AzureWebJobsStorage=UseDevelopmentStorage=true
FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
ProcessGlobalChangeTrackingSchedule=0 23 11 * * *
SyncJobsConfig__Jobs__SyncTest__Area=SyncTest
SyncJobsConfig__Jobs__SyncTest__Source__ConnectionString=Server=localhost;Initial Catalog=SyncTest;Integrated Security=True
SyncJobsConfig__Jobs__SyncTest__Source__ManagedIdentity=false
SyncJobsConfig__Jobs__SyncTest__Target__ConnectionString=Server=localhost;Initial Catalog=SyncTest;Integrated Security=True
SyncJobsConfig__Jobs__SyncTest__Target__ManagedIdentity=false
SyncJobsConfig__Jobs__SyncTest__BatchSize=1000
SyncJobsConfig__Jobs__SyncTest__Manual=false
SyncJobsConfig__Jobs__SyncTest__Tables__Test=source.[Test]
SyncJobsConfig__Jobs__SyncTest__TargetTables__Test=target.[Test]
SyncJobsConfig__Jobs__SyncTest__Schedules__Custom=true
SyncJobsConfig__Jobs__SyncTest__Schedules__Noon=true
SyncJobsConfig__Jobs__SyncTest__Schedules__Midnight=true
SyncJobsConfig__Jobs__SyncTest__Schedules__EveryFiveMinutes=true
SyncJobsConfig__Jobs__SyncTest__Schedules__EveryHour=true
```



### Example database seed script

```sql
Expand Down
87 changes: 46 additions & 41 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
name: $(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)

trigger:
- main

pool:
vmImage: 'windows-latest'

pool: WCOM

variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
artifactName: 'SqlBulkSyncFunction'

steps:
- task: UseDotNet@2.263.0
displayName: 'Use .NET SDK global.json'
inputs:
packageType: sdk
useGlobalJson: true

- script: |
dotnet publish -p:Version=$(Build.BuildNumber) --configuration $(BuildConfiguration) -p:GenerateFullPaths=true --output "$(Build.ArtifactStagingDirectory)/Output" src/SqlBulkSyncFunction/SqlBulkSyncFunction.csproj
displayName: .NET Publish $(ArtifactName)

- script: |
dotnet pack -p:Version=$(Build.BuildNumber) --configuration $(BuildConfiguration) -p:GenerateFullPaths=true --output "$(Build.ArtifactStagingDirectory)/NuGet" src/SqlBulkSyncFunction/SqlBulkSyncFunction.csproj
displayName: .NET Pack $(ArtifactName)

- task: ArchiveFiles@2.265.0
displayName: Archive Output $(ArtifactName)
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/Output
includeRootFolder: false
archiveFile: $(Build.ArtifactStagingDirectory)/$(ArtifactName).zip

- task: PublishPipelineArtifact@1.242.0
displayName: Publish Pipeline Artifact $(ArtifactName) Zip
inputs:
artifactName: $(ArtifactName)
path: $(Build.ArtifactStagingDirectory)/$(ArtifactName).zip

- task: PublishPipelineArtifact@1.242.0
displayName: Publish Pipeline Artifact $(ArtifactName) NuGet
inputs:
artifactName: "$(ArtifactName)NuGet"
path: $(Build.ArtifactStagingDirectory)/NuGet
- group: common-build-variables

resources:
repositories:
- repository: templates
type: github
endpoint: GitHubPublic
name: WCOMAB/WCOM.AzurePipelines.YamlTemplates
ref: refs/heads/main

stages:
- template: dotnetweb/stages.yml@templates
parameters:
devopsOrg: 'wcom'
system: 'sqlbulksync'
suffix: 'sqlbulksync'
webAppName: 'sqlbulksync'
build: Development
useDotNetSDK:
skipTask: true
skipTests: true
projectSrc: ./src/SqlBulkSyncFunction
buildParameters:
- '-c Release'
shouldDeploy: eq(variables['Build.SourceBranch'], 'refs/heads/main')
dpi:
report: eq(variables['Build.SourceBranch'], 'refs/heads/main')
WorkspaceId: $(API.DEV.LogId)
SharedKey: $(API.DEV.LogKey)
environments:
- env: dev
name: Development
deploy: false
container:
csproj: './src/SqlBulkSyncFunction/SqlBulkSyncFunction.csproj'
artifact: 'wcom-sqlbulksync-image'
repository: 'wcom.sqlbulksync'
baseimage: 'mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated10.0'
latest: true
servers:
- name: 'wcompublicacr.azurecr.io'
username: 'wcompublicacr'
password: '$(wcompublicacr.azurecr.io)'
13 changes: 13 additions & 0 deletions nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>
Loading
Loading