/// <summary>
        /// Processes the Push-CloudServices commandlet synchronously.
        /// </summary>
        protected override void ProcessRecord()
        {
            var azureSubscription = new AzureSubscription(SettingsPath, SubscriptionId);
            var azureCert         = new X509Certificate2(Convert.FromBase64String(azureSubscription.ManagementCertificate));
            var credentials       = new CertificateCloudCredentials(SubscriptionId, azureCert);

            FlexStreams.UseThreadQueue(ThreadAdapter);

            using (EventStream.Subscribe(e => WriteObject(e.Message)))
                using (var computeClient = new ComputeManagementClient(credentials))
                    using (var storageClient = new StorageManagementClient(credentials))
                    {
                        var targetSlot = VipSwap ? DeploymentSlot.Staging : DeploymentSlot.Production;

                        var storageAccount = storageClient.CreateContainerIfNotExistsAsync(
                            StorageAccountName,
                            StorageContainer,
                            BlobContainerPublicAccessType.Off, SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List).Result;

                        var blobClient = storageAccount.CreateCloudBlobClient();
                        var container  = blobClient.GetContainerReference(StorageContainer);

                        ProcessAsyncWork(ServiceNames.Select((t, i) => DeployCloudServiceAsync(computeClient, container, t, PackagePaths[i], ConfigurationPaths[i], DiagnosticsConfigurationPaths?[i], targetSlot))
                                         .ToArray());
                    }

            WriteObject("Push-CloudServices completed!");
            base.ProcessRecord();
        }
Example #2
0
        /// <summary>
        /// Checks for the existence of a specific Azure Sql Firewall rule, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="SqlManagementClient"/> that is performing the operation.</param>
        /// <param name="serverName">The name of the server that we want to use to create the database.</param>
        /// <param name="parameters">The <see cref="FirewallRuleCreateParameters"/> set of parameters for the rule.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateFirewallRuleIfNotExistsAsync(this SqlManagementClient client, string serverName, FirewallRuleCreateParameters parameters)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(serverName));
            Contract.Requires(parameters != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(parameters.Name));
            Contract.Requires(!string.IsNullOrWhiteSpace(parameters.StartIPAddress));
            Contract.Requires(!string.IsNullOrWhiteSpace(parameters.EndIPAddress));

            FirewallRuleGetResponse rule = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.FirewallRule, parameters.Name));

            try
            {
                rule = await client.FirewallRules.GetAsync(serverName, parameters.Name);
            }
            catch (CloudException cex)
            {
                if (!cex.Error.Message.Contains($"Resource with the name '{parameters.Name}' does not exist"))
                {
                    throw;
                }
            }

            if (rule != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.FirewallRule, parameters.Name));
                return;
            }

            await client.FirewallRules.CreateAsync(serverName, parameters);

            FlexStreams.Publish(new ProvisionEvent(AzureResource.FirewallRule, parameters.Name));
        }
Example #3
0
        /// <summary>
        /// Checks for the existence of a specific Azure Sql Database, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="SqlManagementClient"/> that is performing the operation.</param>
        /// <param name="serverName">The name of the server that we want to use to create the database.</param>
        /// <param name="databaseName">The name of the database we are creating.</param>
        /// <param name="databaseEdition">The edition of the database we are creating.</param>
        /// <param name="collationName">The database collation name.</param>
        /// <param name="sizeInGb">The maximum database size in GB.</param>
        /// <param name="createAppUser"></param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateDatabaseIfNotExistsAsync(
            this SqlManagementClient client,
            string serverName,
            string databaseName,
            string databaseEdition,
            string collationName,
            int sizeInGb,
            bool createAppUser)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(serverName));
            Contract.Requires(!string.IsNullOrWhiteSpace(databaseName));
            Contract.Requires(!string.IsNullOrWhiteSpace(databaseEdition));
            Contract.Requires(!string.IsNullOrWhiteSpace(collationName));
            Contract.Requires(sizeInGb > 0 && sizeInGb <= 250);

            DatabaseGetResponse ns = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.SqlDatabase, databaseName));

            try
            {
                ns = await client.Databases.GetAsync(serverName, databaseName);
            }
            catch (CloudException cex)
            {
                if (!cex.Error.Message.Contains($"Resource with the name '{databaseName}' does not exist"))
                {
                    throw;
                }
            }

            if (ns != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.SqlDatabase, databaseName));
                return;
            }

            await client.Databases.CreateAsync(
                serverName,
                new DatabaseCreateParameters
            {
                Name                    = databaseName,
                Edition                 = databaseEdition,
                CollationName           = collationName,
                MaximumDatabaseSizeInGB = sizeInGb,
            });

            FlexStreams.Publish(new ProvisionEvent(AzureResource.SqlDatabase, databaseName));

            if (!createAppUser)
            {
                return;
            }

            using (var adb = new DevOpsAzureDatabase(serverName, databaseName, FlexConfiguration.FlexSaUser, FlexConfiguration.FlexSaPwd))
            {
                await adb.CreateDatabaseUserAsync(FlexConfiguration.FlexAppUser, FlexConfiguration.FlexAppUser, "dbo");
            }
        }
        /// <summary>
        /// Checks for the existence of a specific Azure Web Site, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="ServiceBusManagementClient"/> that is performing the operation.</param>
        /// <param name="sbName">The name of the namespace we want to create.</param>
        /// <param name="region">The region where we want to create the namespace.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateNamespaceIfNotExistsAsync(this ServiceBusManagementClient client, string sbName, string region)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(sbName));
            Contract.Requires(!string.IsNullOrWhiteSpace(region));

            ServiceBusNamespaceResponse sb = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.ServiceBus, sbName));

            try
            {
                sb = await client.Namespaces.GetAsync(sbName);
            }
            catch (CloudException cex)
            {
                // TODO: At the moment of this writing, the ErrorCode in the exception was not in place, so it's a general catch with a contains and that's bad.
                // TODO: This needs to change to the proper trapping of the ErrorCode when they put this in place in the MAML.

                if (!cex.Message.Contains("Request to a downlevel service failed."))
                {
                    throw;
                }
            }

            if (sb != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.ServiceBus, sbName));
                return;
            }

            await client.Namespaces.CreateAsync(sbName, region);

            FlexStreams.Publish(new ProvisionEvent(AzureResource.ServiceBus, sbName));
        }
        /// <summary>
        /// Checks for the existence of a specific storage container, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="StorageManagementClient"/> that is performing the operation.</param>
        /// <param name="accountName">The name of the storage account that we want to create the container in.</param>
        /// <param name="containerName">The name of the container that we are about to create.</param>
        /// <param name="publicAccess">The public access level for the container.</param>
        /// <param name="permissions">The set of permissions that the ACL for this container must have.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task <CloudStorageAccount> CreateContainerIfNotExistsAsync(
            this StorageManagementClient client,
            string accountName,
            string containerName,
            BlobContainerPublicAccessType publicAccess,
            SharedAccessBlobPermissions permissions)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(accountName));
            Contract.Requires(!string.IsNullOrWhiteSpace(containerName));
            Contract.Requires(containerName.Length >= 3);
            Contract.Requires(containerName.Length <= 63);

            var key = (await client.StorageAccounts.GetKeysAsync(accountName)).PrimaryKey;

            var storageAccount = CloudStorageAccount.Parse($"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={key}");
            var container      = storageAccount.CreateCloudBlobClient().GetContainerReference(containerName);

            await container.CreateIfNotExistsAsync();

            await container.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = publicAccess });

            FlexStreams.Publish(new ProvisionEvent(AzureResource.StorageContainer, containerName));

            var acl = container.GetSharedAccessSignature(new SharedAccessBlobPolicy {
                Permissions = permissions
            });

            FlexStreams.Publish(new StorageKeyEvent(accountName, containerName, acl));

            return(storageAccount);
        }
        /// <summary>
        /// Checks for the existence of a specific Azure Web Site, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="WebSiteManagementClient"/> that is performing the operation.</param>
        /// <param name="webSpace">The name of the Web Space where the site should be.</param>
        /// <param name="parameters">The <see cref="WebSiteCreateParameters"/> that define the site we want to create.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateWebSiteIfNotExistsAsync(this WebSiteManagementClient client, string webSpace, WebSiteCreateParameters parameters)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(webSpace));
            Contract.Requires(parameters != null);

            WebSiteGetResponse service = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.WebSite, parameters.Name));

            try
            {
                service = await client.WebSites.GetAsync(webSpace, parameters.Name, null);
            }
            catch (CloudException cex)
            {
                if (cex.Error.Code != "NotFound")
                {
                    throw;
                }
            }

            if (service != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.WebSite, parameters.Name));
                return;
            }

            await client.WebSites.CreateAsync(webSpace, parameters);

            FlexStreams.Publish(new ProvisionEvent(AzureResource.WebSite, parameters.Name));
        }
Example #7
0
        /// <summary>
        /// Checks for the existence of a specific Cloud Service, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="ComputeManagementClient"/> that is performing the operation.</param>
        /// <param name="parameters">The <see cref="HostedServiceCreateParameters"/> that define the service we want to create.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateServiceIfNotExistsAsync(this ComputeManagementClient client, HostedServiceCreateParameters parameters)
        {
            Contract.Requires(client != null);
            Contract.Requires(parameters != null);

            HostedServiceGetResponse service = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.CloudService, parameters.ServiceName));

            try
            {
                service = await client.HostedServices.GetAsync(parameters.ServiceName);
            }
            catch (CloudException cex)
            {
                if (cex.Error.Code != "ResourceNotFound")
                {
                    throw;
                }
            }

            if (service != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.CloudService, parameters.ServiceName));
                return;
            }

            await client.HostedServices.CreateAsync(parameters);

            FlexStreams.Publish(new ProvisionEvent(AzureResource.CloudService, parameters.ServiceName));
        }
        /// <summary>
        /// Checks for the existence of a specific storage container, if it doesn't exist it will create it.
        /// It also checks for a specific storage account that suits the system, if it doesn't exist in the subscription
        /// it will create it before attempting to create the container.
        /// </summary>
        /// <param name="client">The <see cref="StorageManagementClient"/> that is performing the operation.</param>
        /// <param name="model">The DevOpsFlex rich model object that contains everything there is to know about this database spec.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateContainerIfNotExistsAsync(this StorageManagementClient client, AzureStorageContainer model)
        {
            Contract.Requires(client != null);
            Contract.Requires(model != null);
            Contract.Requires(model.System != null);

            string accountName;

            lock (StorageAccountGate)
            {
                FlexStreams.Publish(new CheckForParentResourceEvent(AzureResource.StorageAccount, AzureResource.StorageContainer, model.Name));
                accountName = FlexConfiguration.StorageAccountChooser.Choose(client, model.System.StorageType.GetEnumDescription()).Result;
                StorageAccountGetResponse account = null;

                try
                {
                    account = client.StorageAccounts.Get(accountName);
                }
                catch
                {
                    // ignored
                }

                if (account == null)
                {
                    accountName = (model.System.LogicalName + FlexDataConfiguration.StorageAccountString + FlexDataConfiguration.Branch).ToLower();

                    client.StorageAccounts.Create(
                        new StorageAccountCreateParameters
                    {
                        Name        = accountName,
                        Location    = model.System.Location.GetEnumDescription(),
                        AccountType = model.System.StorageType.GetEnumDescription()
                    });

                    FlexStreams.Publish(new ProvisionEvent(AzureResource.StorageAccount, accountName));
                }
                else
                {
                    accountName = account.StorageAccount.Name;
                    FlexStreams.Publish(new FoundExistingEvent(AzureResource.StorageAccount, accountName));
                }
            }

            await client.CreateContainerIfNotExistsAsync(
                accountName,
                FlexConfiguration.GetNaming <AzureStorageContainer>()
                .GetSlotName(model, FlexDataConfiguration.Branch, FlexDataConfiguration.Configuration),
                model.PublicAccess,
                model.Acl);
        }
        /// <summary>
        /// Processes the Push-DevOpsFlexConfiguration commandlet synchronously.
        /// </summary>
        protected override void ProcessRecord()
        {
            FlexDataConfiguration.Branch        = Branch;
            FlexDataConfiguration.Configuration = Configuration;
            FlexStreams.UseThreadQueue(ThreadAdapter);

            using (EventStream.Subscribe(e => WriteObject(e.Message)))
                using (var context = new DevOpsFlexDbContext(SqlConnectionString))
                {
                    ProcessAsyncWork(context.ProvisionAll(SubscriptionId, SettingsPath));
                }

            WriteObject("Push-DevOpsFlexConfiguration completed!");
            base.ProcessRecord();
        }
        /// <summary>
        /// Checks for the existence of a specific Azure Web Site, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="WebSiteManagementClient"/> that is performing the operation.</param>
        /// <param name="model">The DevOpsFlex rich model object that contains everything there is to know about this web site spec.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateWebSiteIfNotExistsAsync(this WebSiteManagementClient client, AzureWebSite model)
        {
            Contract.Requires(client != null);
            Contract.Requires(model != null);

            var    webSpace = model.System.WebSpace.GetEnumDescription();
            string webPlan;

            lock (HostingPlanGate)
            {
                FlexStreams.Publish(new CheckForParentResourceEvent(AzureResource.HostingPlan, AzureResource.WebSite, model.Name));
                webPlan = FlexConfiguration.WebPlanChooser.Choose(client, webSpace).Result;

                if (webPlan == null)
                {
                    var response = client.WebHostingPlans.Create(webSpace,
                                                                 new WebHostingPlanCreateParameters
                    {
                        Name            = model.System.LogicalName + "-" + webSpace,
                        NumberOfWorkers = 1,
                        SKU             = SkuOptions.Standard,
                        WorkerSize      = WorkerSizeOptions.Medium
                    });

                    webPlan = response.WebHostingPlan.Name;
                    FlexStreams.Publish(new ProvisionEvent(AzureResource.HostingPlan, webPlan));
                }
                else
                {
                    FlexStreams.Publish(new FoundExistingEvent(AzureResource.HostingPlan, webPlan));
                }
            }

            await CreateWebSiteIfNotExistsAsync(
                client,
                webSpace,
                new WebSiteCreateParameters
            {
                Name       = FlexDataConfiguration.GetNaming <AzureWebSite>().GetSlotName(model, FlexDataConfiguration.Branch, FlexDataConfiguration.Configuration),
                ServerFarm = webPlan
            });
        }
Example #11
0
        /// <summary>
        /// Checks for the existence of a specific Azure Reserved IP, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="NetworkManagementClient"/> that is performing the operation.</param>
        /// <param name="ipName">The name of the Reserved IP.</param>
        /// <param name="location">The Azure location of the Reserved IP.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task ReserveIpIfNotReservedAsync(this NetworkManagementClient client, string ipName, string location)
        {
            Contract.Requires(client != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(ipName));
            Contract.Requires(!string.IsNullOrWhiteSpace(location));

            NetworkReservedIPGetResponse service = null;

            FlexStreams.Publish(new CheckIfExistsEvent(AzureResource.ReservedIp, ipName));

            try
            {
                service = await client.ReservedIPs.GetAsync(ipName);
            }
            catch (CloudException cex)
            {
                if (cex.Error.Code != "ResourceNotFound")
                {
                    throw;
                }
            }

            if (service != null)
            {
                FlexStreams.Publish(new FoundExistingEvent(AzureResource.ReservedIp, ipName));
                return;
            }

            await client.ReservedIPs.CreateAsync(
                new NetworkReservedIPCreateParameters
            {
                Name     = ipName,
                Location = location
            });

            FlexStreams.Publish(new ProvisionEvent(AzureResource.ReservedIp, ipName));
        }
Example #12
0
        /// <summary>
        /// Checks for the existence of a specific Azure Sql Database, if it doesn't exist it will create it.
        /// </summary>
        /// <param name="client">The <see cref="SqlManagementClient"/> that is performing the operation.</param>
        /// <param name="model">The DevOpsFlex rich model object that contains everything there is to know about this database spec.</param>
        /// <returns>The async <see cref="Task"/> wrapper.</returns>
        public static async Task CreateDatabaseIfNotExistsAsync(this SqlManagementClient client, SqlAzureDb model)
        {
            Contract.Requires(client != null);
            Contract.Requires(model != null);

            string serverName;

            lock (SqlServerGate)
            {
                FlexStreams.Publish(new CheckForParentResourceEvent(AzureResource.SqlServer, AzureResource.SqlDatabase, model.Name));
                serverName = FlexConfiguration.SqlServerChooser.Choose(client, model.System.Location.GetEnumDescription()).Result;

                if (serverName == null)
                {
                    string serverMaxVersion = null;

                    try
                    {
                        client.Servers.Create(
                            new ServerCreateParameters
                        {
                            AdministratorUserName = FlexConfiguration.FlexSaUser,
                            AdministratorPassword = FlexConfiguration.FlexSaPwd,
                            Location = model.System.Location.GetEnumDescription(),
                            Version  = "100.0" // This needs to be an invalid version number
                                               // TODO: START USING DATABASE SIZE.
                        });
                    }
                    catch (CloudException ex)
                    {
                        if (ex.Error.Code == "40856") // SQL Version doesn't exist in the target location
                        {
                            var serverVersions = Regex.Match(ex.Error.Message, "server versions: '([^']*)'.").Groups[1].Value.Split(',');
                            var maxVersion     = serverVersions.Max((s => decimal.Parse(s)));
                            serverMaxVersion = serverVersions.First(s => s.Contains(maxVersion.ToString("F1", CultureInfo.InvariantCulture)));
                        }
                        else
                        {
                            throw;
                        }
                    }

                    serverName = client.Servers.Create(
                        new ServerCreateParameters
                    {
                        AdministratorUserName = FlexConfiguration.FlexSaUser,
                        AdministratorPassword = FlexConfiguration.FlexSaPwd,
                        Location = model.System.Location.GetEnumDescription(),
                        Version  = serverMaxVersion
                    }).ServerName;

                    FlexStreams.Publish(new ProvisionEvent(AzureResource.SqlServer, serverName));
                }
                else
                {
                    FlexStreams.Publish(new FoundExistingEvent(AzureResource.SqlServer, serverName));
                }
            }

            var dbName = FlexConfiguration.GetNaming <SqlAzureDb>()
                         .GetSlotName(
                model,
                FlexDataConfiguration.Branch,
                FlexDataConfiguration.Configuration);

            await client.CreateDatabaseIfNotExistsAsync(serverName, dbName, model.Edition.GetEnumDescription(), model.CollationName, model.MaximumDatabaseSizeInGB, model.CreateAppUser);
        }