private async Task CreateApplication(DeploymentModel deploymentModel, FabricClient fabric, Uri applicationName)
        {
            logger.LogInformation("Starting to create application {@deploymentModel}", deploymentModel);
            await fabric.ApplicationManager.CreateApplicationAsync(
                new ApplicationDescription(
                    applicationName : applicationName,
                    applicationTypeName : deploymentModel.ApplicationTypeName,
                    applicationTypeVersion : deploymentModel.ApplicationTypeVersion,
                    applicationParameters : deploymentModel.Parameters.ToNameValueCollection()
                    )
                );

            logger.LogInformation("Completed to create application {@deploymentModel}", deploymentModel);

            foreach (var serviceDeployment in deploymentModel.ServiceDeployments)
            {
                var serviceName = new Uri($"{applicationName}/{serviceDeployment.ServiceName}");
                logger.LogInformation("creating service for {applicationName} {ServiceName}", applicationName, serviceName);
                var services = await fabric.QueryManager.GetServiceListAsync(applicationName, serviceName);

                if (!services.Any(s => s.ServiceName == serviceName))
                {
                    await fabric.ServiceManager.CreateServiceAsync(description : new StatelessServiceDescription
                    {
                        ServiceTypeName            = serviceDeployment.ServiceTypeName,
                        ApplicationName            = applicationName,
                        ServiceName                = serviceName,
                        PartitionSchemeDescription = new SingletonPartitionSchemeDescription()
                        {
                        }
                    });

                    logger.LogInformation("Service created for {ServiceName}", serviceName);
                }
            }
            logger.LogInformation("Completed to create services {@deploymentModel}", deploymentModel);
        }
        public async Task <IActionResult> CreateDeployment([FromServices] FabricClient fabric, [FromBody] DeploymentModel deploymentModel)
        {
            logger.LogInformation("Using {fabricClient}", fabric.Settings.ClientFriendlyName);



            using (var stream = await new HttpClient().GetStreamAsync(deploymentModel.RemoteUrl))
            {
                var zip   = new ZipArchive(stream, ZipArchiveMode.Read);
                var entry = zip.GetEntry("ApplicationManifest.xml");

                XDocument xDocument = await XDocument.LoadAsync(entry.Open(), LoadOptions.None, HttpContext.RequestAborted);

                deploymentModel.ApplicationTypeName    = xDocument.Root.Attribute("ApplicationTypeName").Value;
                deploymentModel.ApplicationTypeVersion = xDocument.Root.Attribute("ApplicationTypeVersion").Value;

                logger.LogInformation("Updated deployment model {@deploymentModel}", deploymentModel);
            }

            var types = await fabric.QueryManager.GetApplicationTypeListAsync(deploymentModel.ApplicationTypeName);

            if (!types.Any(a => a.ApplicationTypeName == deploymentModel.ApplicationTypeName && a.ApplicationTypeVersion == deploymentModel.ApplicationTypeVersion))
            {
                logger.LogInformation("Starting to provision {@deploymentModel}", deploymentModel);

                //            fabric.ApplicationManager.CreateApplicationAsync(new System.Fabric.Description.ApplicationDescription{ )
                await fabric.ApplicationManager.ProvisionApplicationAsync(
                    new ExternalStoreProvisionApplicationTypeDescription(
                        applicationPackageDownloadUri : new Uri(deploymentModel.RemoteUrl),
                        applicationTypeName : deploymentModel.ApplicationTypeName,
                        applicationTypeVersion : deploymentModel.ApplicationTypeVersion
                        ), TimeSpan.FromMinutes(5), HttpContext.RequestAborted
                    );

                logger.LogInformation("Completed to provision {@deploymentModel}", deploymentModel);
            }

            var applicationName = new Uri($"fabric:/{deploymentModel.ApplicationName}");
            var applications    = await fabric.QueryManager.GetApplicationListAsync(applicationName);

            if (!applications.Any(application => application.ApplicationName == applicationName))
            {
                await CreateApplication(deploymentModel, fabric, applicationName);
            }
            else
            {
                var existing = applications.FirstOrDefault(a => a.ApplicationName == applicationName);

                if (deploymentModel.DeleteIfExists)
                {
                    foreach (var param in existing.ApplicationParameters)
                    {
                        deploymentModel.Parameters.Add(param.Name, param.Value);
                    }

                    await fabric.ApplicationManager.DeleteApplicationAsync(new DeleteApplicationDescription(applicationName));

                    await Task.Delay(1000);
                    await CreateApplication(deploymentModel, fabric, applicationName);
                }
                else
                {
                    var upgrade = new ApplicationUpgradeDescription
                    {
                        ApplicationName = applicationName,
                        TargetApplicationTypeVersion = deploymentModel.ApplicationTypeVersion,
                        UpgradePolicyDescription     = new MonitoredRollingApplicationUpgradePolicyDescription()
                        {
                            UpgradeMode      = RollingUpgradeMode.Monitored,
                            MonitoringPolicy = new RollingUpgradeMonitoringPolicy()
                            {
                                FailureAction = UpgradeFailureAction.Rollback
                            }
                        }
                    };
                    foreach (var param in  existing.ApplicationParameters)
                    {
                        upgrade.ApplicationParameters.Add(param.Name, deploymentModel.Parameters.ContainsKey(param.Name) ? deploymentModel.Parameters[param.Name]: param.Value);
                    }
                    foreach (var param in deploymentModel.Parameters.Where(k => !existing.ApplicationParameters.Any(a => a.Name == k.Key)))
                    {
                        upgrade.ApplicationParameters.Add(param.Key, param.Value);
                    }


                    await fabric.ApplicationManager.UpgradeApplicationAsync(upgrade);
                }
            }



            return(CreatedAtRoute(nameof(CreateDeployment), new { }));
        }