public void GetOctopusTags_FindsMatchingTags_RegardlessOfCase()
        {
            // Arrange
            var tags = new Dictionary <string, string>
            {
                { "oCtoPus-eNviRonMenT", "taggedEnvironment" },
                { "ocTopUs-roLe", "taggedRole" },
                { "OctOpuS-ProJecT", "taggedProject" },
                { "oCtoPus-sPacE", "taggedSpace" },
                { "ocTopUs-teNanT", "taggedTenant" },
            };

            // Act
            var foundTags = AzureWebAppHelper.GetOctopusTags(tags);

            // Assert
            using (new AssertionScope())
            {
                foundTags.Environment.Should().Be("taggedEnvironment");
                foundTags.Role.Should().Be("taggedRole");
                foundTags.Project.Should().Be("taggedProject");
                foundTags.Space.Should().Be("taggedSpace");
                foundTags.Tenant.Should().Be("taggedTenant");
            }
        }
        public void Install(RunningDeployment deployment)
        {
            var variables         = deployment.Variables;
            var subscriptionId    = variables.Get(SpecialVariables.Action.Azure.SubscriptionId);
            var resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty);
            var siteAndSlotName   = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName          = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            var resourceGroupText = string.IsNullOrEmpty(resourceGroupName)
                ? string.Empty
                : $" in Resource Group '{resourceGroupName}'";
            var slotText = targetSite.HasSlot
                ? $", deployment slot '{targetSite.Slot}'"
                : string.Empty;

            Log.Info($"Deploying to Azure WebApp '{targetSite.Site}'{slotText}{resourceGroupText}, using subscription-id '{subscriptionId}'");

            var publishProfile = GetPublishProfile(variables);
            RemoteCertificateValidationCallback originalServerCertificateValidationCallback = null;

            try
            {
                originalServerCertificateValidationCallback             = ServicePointManager.ServerCertificateValidationCallback;
                ServicePointManager.ServerCertificateValidationCallback = WrapperForServerCertificateValidationCallback;
                DeployToAzure(deployment, targetSite, variables, publishProfile);
            }
            finally
            {
                ServicePointManager.ServerCertificateValidationCallback = originalServerCertificateValidationCallback;
            }
        }
        public void PoorlyFormedLegacySite()
        {
            var targetSite = AzureWebAppHelper.GetAzureTargetSite($"{site}({slot}", string.Empty);

            targetSite.HasSlot.Should().BeTrue();
            targetSite.Site.Should().Be(site);
            targetSite.Slot.Should().Be(slot);
        }
        public async Task Execute(RunningDeployment context)
        {
            // Read/Validate variables
            Log.Verbose("Starting App Settings Deploy");
            var variables = context.Variables;

            var principalAccount = ServicePrincipalAccount.CreateFromKnownVariables(variables);

            var webAppName = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName   = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            if (webAppName == null)
            {
                throw new Exception("Web App Name must be specified");
            }

            var resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName);

            if (resourceGroupName == null)
            {
                throw new Exception("resource group name must be specified");
            }

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(webAppName, slotName, resourceGroupName);

            string token = await Auth.GetAuthTokenAsync(principalAccount);

            var webAppClient = new WebSiteManagementClient(new Uri(principalAccount.ResourceManagementEndpointBaseUri),
                                                           new TokenCredentials(token))
            {
                SubscriptionId = principalAccount.SubscriptionNumber,
                HttpClient     = { BaseAddress = new Uri(principalAccount.ResourceManagementEndpointBaseUri) }
            };

            // If app settings are specified
            if (variables.GetNames().Contains(SpecialVariables.Action.Azure.AppSettings) &&
                !string.IsNullOrWhiteSpace(variables[SpecialVariables.Action.Azure.AppSettings]))
            {
                var appSettingsJson = variables.Get(SpecialVariables.Action.Azure.AppSettings, "");
                Log.Verbose($"Updating application settings:\n{appSettingsJson}");
                var appSettings = JsonConvert.DeserializeObject <AppSetting[]>(appSettingsJson);
                await PublishAppSettings(webAppClient, targetSite, appSettings, token);

                Log.Info("Updated application settings");
            }

            // If connection strings are specified
            if (variables.GetNames().Contains(SpecialVariables.Action.Azure.ConnectionStrings) &&
                !string.IsNullOrWhiteSpace(variables[SpecialVariables.Action.Azure.ConnectionStrings]))
            {
                var connectionStringsJson = variables.Get(SpecialVariables.Action.Azure.ConnectionStrings, "");
                Log.Verbose($"Updating connection strings:\n{connectionStringsJson}");
                var connectionStrings = JsonConvert.DeserializeObject <ConnectionStringSetting[]>(connectionStringsJson);
                await PublishConnectionStrings(webAppClient, targetSite, connectionStrings);

                Log.Info("Updated connection strings");
            }
        }
        public void SiteWithNoSlot()
        {
            var targetSite = AzureWebAppHelper.GetAzureTargetSite($"{site}", string.Empty);

            targetSite.HasSlot.Should().BeFalse();
            targetSite.Site.Should().Be(site);
            targetSite.RawSite.Should().Be(site);
            targetSite.Slot.Should().BeNullOrEmpty();
        }
        public void SiteAndSlotInProperty()
        {
            var targetSite = AzureWebAppHelper.GetAzureTargetSite(site, slot);

            targetSite.HasSlot.Should().BeTrue();
            targetSite.Site.Should().Be(site);
            targetSite.RawSite.Should().Be(site);
            targetSite.Slot.Should().Be(slot);
            targetSite.SiteAndSlot.Should().Be($"{site}/{slot}");
        }
        public void SiteWithSlotSlashFormat()
        {
            var siteAndMaybeSlotName = $"{site}/{slot}";
            var targetSite           = AzureWebAppHelper.GetAzureTargetSite(siteAndMaybeSlotName, string.Empty);

            targetSite.HasSlot.Should().BeTrue();
            targetSite.Site.Should().Be(site);
            targetSite.RawSite.Should().Be(siteAndMaybeSlotName);
            targetSite.Slot.Should().Be(slot);
        }
        public void LegacySiteWithSlot()
        {
            var siteAndMaybeSlotName = $"{site}({slot})";
            var targetSite           = AzureWebAppHelper.GetAzureTargetSite(siteAndMaybeSlotName, string.Empty);

            targetSite.HasSlot.Should().BeTrue();
            targetSite.Site.Should().Be(this.site);
            targetSite.RawSite.Should().Be(siteAndMaybeSlotName);
            targetSite.Slot.Should().Be(this.slot);
        }
        Task <WebDeployPublishSettings> GetPublishProfile(IVariables variables)
        {
            var account         = new AzureServicePrincipalAccount(variables);
            var siteAndSlotName = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName        = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);
            var targetSite      = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            return(resourceManagerPublishProfileProvider.GetPublishProperties(account,
                                                                              variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty),
                                                                              targetSite));
        }
Exemple #10
0
        public async Task AzureLinuxContainerDeploy()
        {
            newVariables = new CalamariVariables();
            AddVariables(newVariables);

            var runningContext = new RunningDeployment("", newVariables);

            await new AzureAppServiceDeployContainerBehavior(new InMemoryLog()).Execute(runningContext);

            await AssertDeploySuccessAsync(AzureWebAppHelper.GetAzureTargetSite(site.Name, "", resourceGroupName));
        }
        public void SiteWithSlotInSiteNameAndSlotInProperty()
        {
            var overrideSlot         = Guid.NewGuid().ToString();
            var siteAndMaybeSlotName = $"{site}/{slot}";
            var targetSite           = AzureWebAppHelper.GetAzureTargetSite(siteAndMaybeSlotName, overrideSlot);

            targetSite.HasSlot.Should().BeTrue();
            targetSite.Site.Should().Be(site);
            targetSite.RawSite.Should().Be(siteAndMaybeSlotName);
            targetSite.Slot.Should().Be(slot);
        }
Exemple #12
0
        public async Task AzureLinuxContainerSlotDeploy()
        {
            var slotName = "stage";

            newVariables = new CalamariVariables();
            AddVariables(newVariables);
            newVariables.Add("Octopus.Action.Azure.DeploymentSlot", slotName);
            var slot = await webMgmtClient.WebApps.BeginCreateOrUpdateSlotAsync(resourceGroupName, webappName, site,
                                                                                slotName);

            var runningContext = new RunningDeployment("", newVariables);

            await new AzureAppServiceDeployContainerBehavior(new InMemoryLog()).Execute(runningContext);

            await AssertDeploySuccessAsync(AzureWebAppHelper.GetAzureTargetSite(site.Name, slotName, resourceGroupName));
        }
Exemple #13
0
        private static WebDeployPublishSettings GetPublishProfile(IVariables variables)
        {
            var account = new AzureServicePrincipalAccount(variables);

            var siteAndSlotName = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName        = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            if (account is AzureServicePrincipalAccount servicePrincipalAccount)
            {
                return(ResourceManagerPublishProfileProvider.GetPublishProperties(servicePrincipalAccount,
                                                                                  variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty),
                                                                                  targetSite));
            }

            throw new CommandException("Account type must be Azure Service Principal");
        }
Exemple #14
0
        public async Task Execute(RunningDeployment context)
        {
            var variables = context.Variables;

            var principalAccount = ServicePrincipalAccount.CreateFromKnownVariables(variables);
            var webAppName       = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName         = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);
            var rgName           = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName);
            var targetSite       = AzureWebAppHelper.GetAzureTargetSite(webAppName, slotName, rgName);

            var image        = variables.Get(SpecialVariables.Action.Package.Image);
            var registryHost = variables.Get(SpecialVariables.Action.Package.Registry);
            var regUsername  = variables.Get(SpecialVariables.Action.Package.Feed.Username);
            var regPwd       = variables.Get(SpecialVariables.Action.Package.Feed.Password);

            var token = await Auth.GetAuthTokenAsync(principalAccount);

            var webAppClient = new WebSiteManagementClient(new Uri(principalAccount.ResourceManagementEndpointBaseUri),
                                                           new TokenCredentials(token))
            {
                SubscriptionId = principalAccount.SubscriptionNumber
            };

            Log.Info($"Updating web app to use image {image} from registry {registryHost}");

            Log.Verbose("Retrieving config (this is required to update image)");
            var config = await webAppClient.WebApps.GetConfigurationAsync(targetSite);

            config.LinuxFxVersion = $@"DOCKER|{image}";


            Log.Verbose("Retrieving app settings");
            var appSettings = await webAppClient.WebApps.ListApplicationSettingsAsync(targetSite);

            appSettings.Properties["DOCKER_REGISTRY_SERVER_URL"]      = "https://" + registryHost;
            appSettings.Properties["DOCKER_REGISTRY_SERVER_USERNAME"] = regUsername;
            appSettings.Properties["DOCKER_REGISTRY_SERVER_PASSWORD"] = regPwd;

            Log.Info("Updating app settings with container registry");
            await webAppClient.WebApps.UpdateApplicationSettingsAsync(targetSite, appSettings);

            Log.Info("Updating configuration with container image");
            await webAppClient.WebApps.UpdateConfigurationAsync(targetSite, config);
        }
        private static SitePublishProfile GetPublishProfile(VariableDictionary variables)
        {
            var subscriptionId  = variables.Get(SpecialVariables.Action.Azure.SubscriptionId);
            var accountType     = variables.Get(SpecialVariables.Account.AccountType);
            var siteAndSlotName = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName        = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            switch (accountType)
            {
            case AzureAccountTypes.ServicePrincipalAccountType:
                var resourceManagementEndpoint = variables.Get(SpecialVariables.Action.Azure.ResourceManagementEndPoint, DefaultVariables.ResourceManagementEndpoint);
                if (resourceManagementEndpoint != DefaultVariables.ResourceManagementEndpoint)
                {
                    Log.Info("Using override for resource management endpoint - {0}", resourceManagementEndpoint);
                }

                var activeDirectoryEndpoint = variables.Get(SpecialVariables.Action.Azure.ActiveDirectoryEndPoint, DefaultVariables.ActiveDirectoryEndpoint);
                if (activeDirectoryEndpoint != DefaultVariables.ActiveDirectoryEndpoint)
                {
                    Log.Info("Using override for Azure Active Directory endpoint - {0}", activeDirectoryEndpoint);
                }

                return(ResourceManagerPublishProfileProvider.GetPublishProperties(subscriptionId, variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty), targetSite, variables.Get(SpecialVariables.Action.Azure.TenantId), variables.Get(SpecialVariables.Action.Azure.ClientId), variables.Get(SpecialVariables.Action.Azure.Password), resourceManagementEndpoint, activeDirectoryEndpoint));

            case AzureAccountTypes.ManagementCertificateAccountType:
                var serviceManagementEndpoint = variables.Get(SpecialVariables.Action.Azure.ServiceManagementEndPoint, DefaultVariables.ServiceManagementEndpoint);
                if (serviceManagementEndpoint != DefaultVariables.ServiceManagementEndpoint)
                {
                    Log.Info("Using override for service management endpoint - {0}", serviceManagementEndpoint);
                }

                return(ServiceManagementPublishProfileProvider.GetPublishProperties(subscriptionId,
                                                                                    Convert.FromBase64String(variables.Get(SpecialVariables.Action.Azure.CertificateBytes)),
                                                                                    targetSite,
                                                                                    serviceManagementEndpoint));

            default:
                throw new CommandException(
                          "Account type must be either Azure Management Certificate or Azure Service Principal");
            }
        }
Exemple #16
0
        public async Task Execute(RunningDeployment context)
        {
            var variables         = context.Variables;
            var webAppName        = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName          = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);
            var resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName);
            var targetSite        = AzureWebAppHelper.GetAzureTargetSite(webAppName, slotName, resourceGroupName);

            var principalAccount = ServicePrincipalAccount.CreateFromKnownVariables(variables);
            var token            = await Auth.GetAuthTokenAsync(principalAccount);

            var webAppClient = new WebSiteManagementClient(new Uri(principalAccount.ResourceManagementEndpointBaseUri), new TokenCredentials(token))
            {
                SubscriptionId = principalAccount.SubscriptionNumber
            };

            Log.Info("Performing soft restart of web app");
            await webAppClient.WebApps.RestartAsync(targetSite, true);
        }
        public void Install(RunningDeployment deployment)
        {
            try
            {
                var variables         = deployment.Variables;
                var resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty);
                var siteAndSlotName   = variables.Get(SpecialVariables.Action.Azure.WebAppName);
                var slotName          = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);
                var targetSite        = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);
                var azureEnvironment  = variables.Get(SpecialVariables.Action.Azure.Environment);
                var account           = AccountFactory.Create(variables);

                if (account is AzureServicePrincipalAccount servicePrincipalAccount)
                {
                    var client = servicePrincipalAccount.CreateWebSiteManagementClient();
                    var site   = client?.WebApps.Get(resourceGroupName, siteAndSlotName);
                    if (site != null)
                    {
                        var portalUrl = GetAzurePortalUrl(azureEnvironment);

                        Log.Info($"Default Host Name: {site.DefaultHostName}");
                        Log.Info($"Application state: {site.State}");
                        Log.Info("Links:");
                        LogLink($"https://{site.DefaultHostName}");

                        if (!site.HttpsOnly.HasValue || site.HttpsOnly == false)
                        {
                            LogLink($"http://{site.DefaultHostName}");
                        }

                        string portalUri = $"https://{portalUrl}/#@/resource{site.Id}";

                        LogLink("View in Azure Portal", portalUri);
                    }
                }
            }
            catch
            {
                // do nothing
            }
        }
        private static WebDeployPublishSettings GetPublishProfile(VariableDictionary variables)
        {
            var account = AccountFactory.Create(variables);

            var siteAndSlotName = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName        = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            if (account is AzureServicePrincipalAccount servicePrincipalAccount)
            {
                return(ResourceManagerPublishProfileProvider.GetPublishProperties(servicePrincipalAccount,
                                                                                  variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty),
                                                                                  targetSite));
            }
            else if (account is AzureAccount azureAccount)
            {
                return(new WebDeployPublishSettings(targetSite.Site, ServiceManagementPublishProfileProvider.GetPublishProperties(azureAccount, targetSite)));
            }

            throw new CommandException("Account type must be either Azure Management Certificate or Azure Service Principal");
        }
Exemple #19
0
        public void Install(RunningDeployment deployment)
        {
            var variables = deployment.Variables;

            if (variables.Get(SpecialVariables.Account.AccountType) == "AzureSubscription")
            {
                log.Warn("Use of Management Certificates to deploy Azure Web App services has been deprecated by Microsoft and they are progressively disabling them, please update to using a Service Principal. If you receive an error about the app not being found in the subscription then this account type is the most likely cause. See [our documentation](https://g.octopushq.com/AzureTargets#azure-management-certificate) for more details.");
            }

            var subscriptionId    = variables.Get(SpecialVariables.Action.Azure.SubscriptionId);
            var resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName, string.Empty);
            var siteAndSlotName   = variables.Get(SpecialVariables.Action.Azure.WebAppName);
            var slotName          = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(siteAndSlotName, slotName);

            var resourceGroupText = string.IsNullOrEmpty(resourceGroupName)
                ? string.Empty
                : $" in Resource Group '{resourceGroupName}'";
            var slotText = targetSite.HasSlot
                ? $", deployment slot '{targetSite.Slot}'"
                : string.Empty;

            log.Info($"Deploying to Azure WebApp '{targetSite.Site}'{slotText}{resourceGroupText}, using subscription-id '{subscriptionId}'");

            var publishSettings = GetPublishProfile(variables);
            RemoteCertificateValidationCallback originalServerCertificateValidationCallback = null;

            try
            {
                originalServerCertificateValidationCallback             = ServicePointManager.ServerCertificateValidationCallback;
                ServicePointManager.ServerCertificateValidationCallback = WrapperForServerCertificateValidationCallback;
                DeployToAzure(deployment, targetSite, variables, publishSettings);
            }
            finally
            {
                ServicePointManager.ServerCertificateValidationCallback = originalServerCertificateValidationCallback;
            }
        }
Exemple #20
0
        public async Task Execute(RunningDeployment runningDeployment)
        {
            await Task.CompletedTask;
            var targetDiscoveryContext = GetTargetDiscoveryContext(runningDeployment.Variables);

            if (targetDiscoveryContext?.Authentication == null || targetDiscoveryContext.Scope == null)
            {
                Log.Warn("Aborting target discovery.");
                return;
            }
            var account = targetDiscoveryContext.Authentication.AccountDetails;

            Log.Verbose($"Looking for Azure web apps using:");
            Log.Verbose($"  Subscription ID: {account.SubscriptionNumber}");
            Log.Verbose($"  Tenant ID: {account.TenantId}");
            Log.Verbose($"  Client ID: {account.ClientId}");
            var azureClient = account.CreateAzureClient();

            try
            {
                var discoveredTargetCount = 0;
                var webApps = ListWebApps(azureClient);
                Log.Verbose($"Found {webApps.Count()} candidate web apps.");
                foreach (var webApp in webApps)
                {
                    var tags        = AzureWebAppHelper.GetOctopusTags(webApp.Tags);
                    var matchResult = targetDiscoveryContext.Scope.Match(tags);
                    if (matchResult.IsSuccess)
                    {
                        discoveredTargetCount++;
                        Log.Info($"Discovered matching web app: {webApp.Name}");
                        WriteTargetCreationServiceMessage(
                            webApp, targetDiscoveryContext, matchResult);
                    }
                    else
                    {
                        Log.Verbose($"Web app {webApp.Name} does not match target requirements:");
                        foreach (var reason in matchResult.FailureReasons)
                        {
                            Log.Verbose($"- {reason}");
                        }
                    }

                    Log.Verbose($"Looking for deployment slots in web app {webApp.Name}");

                    var deploymentSlots = ListDeploymentSlots(webApp);

                    foreach (var slot in deploymentSlots)
                    {
                        var deploymentSlotTags        = AzureWebAppHelper.GetOctopusTags(slot.Tags);
                        var deploymentSlotMatchResult = targetDiscoveryContext.Scope.Match(deploymentSlotTags);
                        if (deploymentSlotMatchResult.IsSuccess)
                        {
                            discoveredTargetCount++;
                            Log.Info($"Discovered matching deployment slot {slot.Name} in web app {webApp.Name}");
                            WriteDeploymentSlotTargetCreationServiceMessage(
                                webApp, slot, targetDiscoveryContext, deploymentSlotMatchResult);
                        }
                        else
                        {
                            Log.Verbose($"Deployment slot {slot.Name} in web app {webApp.Name} does not match target requirements:");
                            foreach (var reason in matchResult.FailureReasons)
                            {
                                Log.Verbose($"- {reason}");
                            }
                        }
                    }
                }

                if (discoveredTargetCount > 0)
                {
                    Log.Info($"{discoveredTargetCount} targets found.");
                }
                else
                {
                    Log.Warn($"Could not find any Azure web app targets.");
                }
            }
            catch (Exception ex)
            {
                Log.Warn($"Error connecting to Azure to look for web apps:");
                Log.Warn(ex.Message);
                Log.Warn("Aborting target discovery.");
            }
        }
Exemple #21
0
        public async Task Execute(RunningDeployment context)
        {
            var    variables        = context.Variables;
            var    servicePrincipal = ServicePrincipalAccount.CreateFromKnownVariables(variables);
            string?webAppName       = variables.Get(SpecialVariables.Action.Azure.WebAppName);

            if (webAppName == null)
            {
                throw new Exception("Web App Name must be specified");
            }
            string?resourceGroupName = variables.Get(SpecialVariables.Action.Azure.ResourceGroupName);

            if (resourceGroupName == null)
            {
                throw new Exception("resource group name must be specified");
            }
            string?slotName        = variables.Get(SpecialVariables.Action.Azure.WebAppSlot);
            var    packageFileInfo = new FileInfo(variables.Get(TentacleVariables.CurrentDeployment.PackageFilePath) !);

            switch (packageFileInfo.Extension)
            {
            case ".zip":
                Archive = new ZipPackageProvider();
                break;

            case ".nupkg":
                Archive = new NugetPackageProvider();
                break;

            case ".war":
                Archive = new WarPackageProvider(Log, variables, context);
                break;

            default:
                throw new Exception("Unsupported archive type");
            }

            var azureClient = servicePrincipal.CreateAzureClient();
            var webApp      = await azureClient.WebApps.GetByResourceGroupAsync(resourceGroupName, webAppName);

            var targetSite = AzureWebAppHelper.GetAzureTargetSite(webAppName, slotName, resourceGroupName);

            // Lets process our archive while the slot is spun up.  we will await it later before we try to upload to it.
            var slotCreateTask = new Task(() => { });

            if (targetSite.HasSlot)
            {
                slotCreateTask = FindOrCreateSlot(webApp, targetSite);
            }

            string[]? substitutionFeatures =
            {
                KnownVariables.Features.ConfigurationTransforms,
                KnownVariables.Features.StructuredConfigurationVariables,
                KnownVariables.Features.SubstituteInFiles
            };

            /*
             * Calamari default behaviors
             * https://github.com/OctopusDeploy/Calamari/tree/master/source/Calamari.Common/Features/Behaviours
             */

            var uploadPath = string.Empty;

            if (substitutionFeatures.Any(featureName => context.Variables.IsFeatureEnabled(featureName)))
            {
                uploadPath = (await Archive.PackageArchive(context.StagingDirectory, context.CurrentDirectory))
                             .FullName;
            }
            else
            {
                uploadPath = (await Archive.ConvertToAzureSupportedFile(packageFileInfo)).FullName;
            }

            if (uploadPath == null)
            {
                throw new Exception("Package File Path must be specified");
            }

            // need to ensure slot is created as slot creds may be used
            if (targetSite.HasSlot)
            {
                await slotCreateTask;
            }

            var publishingProfile = await PublishingProfile.GetPublishingProfile(targetSite, servicePrincipal);

            string?credential = await Auth.GetBasicAuthCreds(servicePrincipal, targetSite);

            string token = await Auth.GetAuthTokenAsync(servicePrincipal);

            var webAppClient = new WebSiteManagementClient(new Uri(servicePrincipal.ResourceManagementEndpointBaseUri),
                                                           new TokenCredentials(token))
            {
                SubscriptionId = servicePrincipal.SubscriptionNumber
            };

            var httpClient = webAppClient.HttpClient;

            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credential);

            Log.Info($"Uploading package to {targetSite.SiteAndSlot}");

            await UploadZipAsync(publishingProfile, httpClient, uploadPath, targetSite.ScmSiteAndSlot);
        }