public static async Task Main()

in SQL-Hybrid-Cloud-Toolkit/Components/ADP/SqlPackageWrapper/Program.cs [30:160]


        public static async Task<int> Main(string[] args)
        {
            var assembly = typeof(Program).Assembly;
            WriteLine($"{assembly.ManifestModule.Name} v{assembly.GetName().Version.ToString(3)}");

            // Get the command payload 
            var payload = new Payload();

            if (args.Length > 0)
            {
                payload.Action = (ActionType)Enum.Parse(typeof(ActionType), args[0]);
                payload.LogicalServerName = args[1] + ".database.windows.net";
                payload.DatabaseName = args[2];
                payload.Username = args[3];
                payload.Password = args[4];
                payload.SqlPackageVersion = args[5];
            }

            // Cleanup folders
            foreach (string dir in directories)
            {
                if (Directory.Exists(dir))
                {
                    Directory.Delete(dir, true);
                }

                Directory.CreateDirectory(dir);
            }

            string sqlPackageDataPath = Path.Combine(dataDirectory, payload.DatabaseName + ".bacpac");
            string sqlPackageLogPath = Path.Combine(dataDirectory, payload.DatabaseName + ".log");

            var targetDir = Environment.GetEnvironmentVariable($"{Constants.EnvironmentVariableNames.SqlPackageLocation}#{payload.SqlPackageVersion}");
            var workingDir = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableNames.TaskWorkingDir);

            string taskId = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableNames.AzBatchTaskId);
            string jobContainerUrl = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableNames.JobContainerUrl);

            // Build the import/export command
            var cmdBuilder = new StringBuilder();
            cmdBuilder.Append($"/Action:{payload.Action}");
            cmdBuilder.Append(" /MaxParallelism:16");
            cmdBuilder.Append(String.Format(" /DiagnosticsFile:{0}", sqlPackageLogPath));
            cmdBuilder.Append(" /p:CommandTimeout=86400");

            switch (payload.Action)
            {
                case ActionType.Export:
                    cmdBuilder.Append($" /SourceServerName:{payload.LogicalServerName}");
                    cmdBuilder.Append($" /SourceDatabaseName:{payload.DatabaseName}");
                    cmdBuilder.Append($" /SourceUser:{payload.Username}");
                    cmdBuilder.Append($" /SourcePassword:{payload.Password}");
                    cmdBuilder.Append($" /TargetFile:{sqlPackageDataPath}");
                    cmdBuilder.Append(String.Format(" /p:TempDirectoryForTableData=\"{0}\"", tempDirectory));
                    cmdBuilder.Append(" /p:VerifyFullTextDocumentTypesSupported=false");
                    break;

                case ActionType.Import:
                    cmdBuilder.Append($" /TargetServerName:{payload.LogicalServerName}");
                    cmdBuilder.Append($" /TargetDatabaseName:{payload.DatabaseName}");
                    cmdBuilder.Append($" /TargetUser:{payload.Username}");
                    cmdBuilder.Append($" /TargetPassword:{payload.Password}");
                    cmdBuilder.Append($" /SourceFile:{sqlPackageDataPath}");
                    break;

                default:
                    throw new ArgumentException($"Invalid action type: {payload.Action}");
            }

            if (payload.Action == ActionType.Import)
            {
                WriteLine(string.Format("Downloading {0} bacpac file to {1}", payload.DatabaseName, sqlPackageDataPath));
                CloudBlobContainer container = new CloudBlobContainer(new Uri(jobContainerUrl));
                CloudBlockBlob blob = container.GetBlockBlobReference(String.Format("$JobOutput/{0}.bacpac", payload.DatabaseName));
                await blob.DownloadToFileAsync(sqlPackageDataPath, FileMode.CreateNew);
                WriteLine(string.Format("Downloaded {0} bacpac file to {1}", payload.DatabaseName, sqlPackageDataPath));
                
                await Task.Delay(stdoutFlushDelay);
            }

            // Perform the import/export process
            var startTime = DateTimeOffset.UtcNow;
            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    WorkingDirectory = workingDir,
                    FileName = Path.Combine(targetDir, "sqlpackage.exe"),
                    Arguments = cmdBuilder.ToString(),
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                }
            };
            process.OutputDataReceived += (s, e) => WriteLine(e.Data);
            process.ErrorDataReceived += (s, e) => WriteErrorLine(e.Data);
            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            process.WaitForExit();

            WriteLine(String.Format("SqlPackage.exe exited with code: {0}", process.ExitCode));

            if (payload.Action == ActionType.Export)
            {
                // Persist the Job Output 
                JobOutputStorage jobOutputStorage = new JobOutputStorage(new Uri(jobContainerUrl));

                await jobOutputStorage.SaveAsync(JobOutputKind.JobOutput, sqlPackageLogPath, payload.DatabaseName + ".log");
                WriteLine(String.Format("Uploaded {0} to job account", sqlPackageLogPath));

                await jobOutputStorage.SaveAsync(JobOutputKind.JobOutput, sqlPackageDataPath, payload.DatabaseName + ".bacpac");
                WriteLine(String.Format("Uploaded {0} to job account", sqlPackageDataPath));

                // We are tracking the disk file to save our standard output, but the node agent may take
                // up to 3 seconds to flush the stdout stream to disk. So give the file a moment to catch up.
                await Task.Delay(stdoutFlushDelay);
            }

            // Cleanup folders
            foreach (string dir in directories)
            {
                if (Directory.Exists(dir))
                {
                    Directory.Delete(dir, true);
                }
            }

            return process.ExitCode;
        }