/// <inheritdoc/> public async Task <IServiceBusResource> CreateAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } var client = await CreateClientAsync(resourceGroup); name = await client.ServiceBusNamespaces.SelectResourceNameAsync( resourceGroup.Name, "sb", name); _logger.Info($"Trying to create namespace {name}..."); var region = await resourceGroup.Subscription.GetRegionAsync(); var nameSpace = await client.ServiceBusNamespaces .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .WithNewManageRule("manage") .WithNewListenRule("listen") .WithNewSendRule("send") .CreateAsync(); _logger.Info($"Created namespace {name}."); var keys = await ReadKeysFromNamespace(nameSpace); return(new ServiceBusResource(this, resourceGroup, nameSpace, keys, _logger)); }
/// <summary> /// Create ubuntu server 16.04 LTS vm /// </summary> public static Task <IVirtualMachineResource> CreateXenialAsync( this IVirtualMachineFactory service, IResourceGroupResource resourceGroup, string name = null, INetworkResource network = null, string customData = null) { return(service.CreateAsync(resourceGroup, name, network, KnownImages.Ubuntu_16_04_lts, customData)); }
/// <inheritdoc/> public async Task <IServiceBusResource> GetAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var client = await CreateClientAsync(resourceGroup); var nameSpace = await client.ServiceBusNamespaces.GetByResourceGroupAsync( resourceGroup.Name, name); if (nameSpace == null) { return(null); } var keys = await ReadKeysFromNamespace(nameSpace); return(new ServiceBusResource(this, resourceGroup, nameSpace, keys, _logger)); }
/// <inheritdoc/> public async Task <IVirtualMachineResource> GetAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var client = await CreateClientAsync(resourceGroup); var vm = await client.VirtualMachines.GetByResourceGroupAsync( resourceGroup.Name, name); if (vm == null) { return(null); } var user = VirtualMachineResource.kDefaultUser; var pw = "Vm$" + name.ToSha1Hash().Substring(0, 3); return(new VirtualMachineResource(this, resourceGroup, vm, user, pw, _logger)); }
/// <summary> /// Create resource /// </summary> /// <param name="manager"></param> /// <param name="resourceGroup"></param> /// <param name="nameSpace"></param> /// <param name="result"></param> /// <param name="logger"></param> public ServiceBusResource(ServiceBusFactory manager, IResourceGroupResource resourceGroup, IServiceBusNamespace nameSpace, Dictionary <string, IAuthorizationKeys> result, ILogger logger) { _resourceGroup = resourceGroup; _nameSpace = nameSpace; _manager = manager; _logger = logger; if (result.TryGetValue("manage", out var key)) { PrimaryManageConnectionString = key.PrimaryConnectionString; SecondaryManageConnectionString = key.SecondaryConnectionString; } if (result.TryGetValue("listen", out key)) { PrimaryListenConnectionString = key.PrimaryConnectionString; SecondaryListenConnectionString = key.SecondaryConnectionString; } if (result.TryGetValue("send", out key)) { PrimarySendConnectionString = key.PrimaryConnectionString; SecondarySendConnectionString = key.SecondaryConnectionString; } }
/// <summary> /// Select virtual machine size /// </summary> /// <param name="resourceGroup"></param> /// <param name="client"></param> /// <returns></returns> private async Task <Tuple <string, string> > SelectRegionAndVmSizeAsync( IResourceGroupResource resourceGroup, IAzure client) { var skus = await client.ComputeSkus.ListByResourceTypeAsync( ComputeResourceType.VirtualMachines); var all = skus .Where(s => !(s.Restrictions?.Any() ?? false)) .Where(s => Satisfies(s.Capabilities)) .SelectMany(s => s.Regions, Tuple.Create) .GroupBy(k => k.Item2.Name, k => k.Item1) .ToDictionary(k => k.Key, v => v); var selected = await resourceGroup.Subscription.GetRegionAsync(); while (true) { if (all.TryGetValue(selected, out var skuSelections)) { // Region is supported select size var sizes = skuSelections .OrderBy(s => s.Costs?.Sum(c => c.Quantity ?? 0) ?? 0) .Select(s => s.VirtualMachineSizeType.Value); if (sizes.Any()) { return(Tuple.Create(selected, sizes.First())); } } // Select different region selected = _selector.SelectRegion(all.Keys.Distinct()); if (selected == null) { return(null); } } }
/// <summary> /// Delete all vm resources if possible /// </summary> /// <returns></returns> public async Task TryDeleteServiceBusAsync( IResourceGroupResource resourceGroup, string id) { var client = await CreateClientAsync(resourceGroup); await Try.Async(() => client.ServiceBusNamespaces.DeleteByIdAsync(id)); }
/// <inheritdoc/> public async Task <IIoTHubResource> GetAsync( IResourceGroupResource resourceGroup, string hubName) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (string.IsNullOrEmpty(hubName)) { throw new ArgumentNullException(nameof(hubName)); } var client = await CreateIoTHubClientAsync(resourceGroup); var hub = await client.IotHubResource.GetAsync( resourceGroup.Name, hubName); if (hub == null) { return(null); } var keys = await client.IotHubResource.GetKeysForKeyNameAsync( resourceGroup.Name, hubName, kIoTHubOwner); if (keys == null) { return(null); } return(new IoTHubResource(this, resourceGroup, hubName, hub.Properties, _logger, keys)); }
/// <summary> /// Delete all vm resources if possible /// </summary> /// <returns></returns> public async Task TryDeleteStorageAsync( IResourceGroupResource resourceGroup, string id) { var client = await CreateClientAsync(resourceGroup); await Try.Async(() => client.StorageAccounts.DeleteByIdAsync(id)); }
/// <summary> /// Delete all vm resources if possible /// </summary> /// <returns></returns> public async Task TryDeleteNetworkAsync( IResourceGroupResource resourceGroup, string id) { var client = await CreateClientAsync(resourceGroup); await Try.Async(() => client.Networks.DeleteByIdAsync(id)); }
/// <inheritdoc/> public async Task <IStorageResource> GetAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var client = await CreateClientAsync(resourceGroup); var storage = await client.StorageAccounts.GetByResourceGroupAsync( resourceGroup.Name, name); if (storage == null) { return(null); } var keys = await storage.GetKeysAsync(); if (keys == null) { return(null); } return(new StorageResource(this, resourceGroup, storage, keys, _logger)); }
/// <inheritdoc/> public async Task <IStorageResource> CreateAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } var client = await CreateClientAsync(resourceGroup); name = await client.StorageAccounts.SelectResourceNameAsync( resourceGroup.Name, "stg", name); var region = await resourceGroup.Subscription.GetRegionAsync(); _logger.Information("Trying to create storage {name}...", name); var storage = await client.StorageAccounts .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .WithAccessFromAllNetworks() .WithGeneralPurposeAccountKindV2() .CreateAsync(); _logger.Information("Created storage {name}.", name); var keys = await storage.GetKeysAsync(); return(new StorageResource(this, resourceGroup, storage, keys, _logger)); }
/// <summary> /// Create resource /// </summary> /// <param name="manager"></param> /// <param name="resourceGroup"></param> /// <param name="network"></param> /// <param name="logger"></param> public NetworkResource(NetworkFactory manager, IResourceGroupResource resourceGroup, INetwork network, ILogger logger) { _resourceGroup = resourceGroup; _network = network; _manager = manager; _logger = logger; }
/// <summary> /// Delete all vm resources if possible /// </summary> /// <returns></returns> public async Task TryDeleteResourcesAsync( IResourceGroupResource resourceGroup, string id) { var client = await CreateClientAsync(resourceGroup); await Try.Async(() => client.VirtualMachines.DeleteByIdAsync(id)); await Try.Async(() => client.Networks.DeleteByIdAsync(id)); await Try.Async(() => client.PublicIPAddresses.DeleteByIdAsync(id)); }
/// <summary> /// Get or create new vm in a resource group. /// </summary> /// <param name="service"></param> /// <param name="resourceGroup"></param> /// <param name="name"></param> /// <param name="network"></param> /// <param name="image"></param> /// <returns></returns> public static async Task <IVirtualMachineResource> GetOrCreateAsync( this IVirtualMachineFactory service, IResourceGroupResource resourceGroup, string name, INetworkResource network = null, VirtualMachineImage image = null) { var resource = await Try.Async(() => service.GetAsync(resourceGroup, name)); if (resource == null) { resource = await service.CreateAsync(resourceGroup, name, network, image, null); } return(resource); }
/// <summary> /// Create resource /// </summary> /// <param name="manager"></param> /// <param name="resourceGroup"></param> /// <param name="vm"></param> /// <param name="user"></param> /// <param name="password"></param> /// <param name="logger"></param> public VirtualMachineResource(VirtualMachineFactory manager, IResourceGroupResource resourceGroup, IVirtualMachine vm, string user, string password, ILogger logger) { _resourceGroup = resourceGroup; _vm = vm; _manager = manager; _logger = logger; User = user; Password = password; }
/// <summary> /// Get or create new storage in a resource group. /// </summary> /// <param name="service"></param> /// <param name="resourceGroup"></param> /// <param name="name"></param> /// <returns></returns> public static async Task <IStorageResource> GetOrCreateAsync( this IStorageFactory service, IResourceGroupResource resourceGroup, string name) { var resource = await Try.Async(() => service.GetAsync(resourceGroup, name)); if (resource == null) { resource = await service.CreateAsync(resourceGroup, name); } return(resource); }
/// <summary> /// Create resource /// </summary> /// <param name="manager"></param> /// <param name="resourceGroup"></param> /// <param name="keys"></param> /// <param name="logger"></param> /// <param name="storage"></param> public StorageResource(StorageFactory manager, IResourceGroupResource resourceGroup, IStorageAccount storage, IReadOnlyList <StorageAccountKey> keys, ILogger logger) { _resourceGroup = resourceGroup; _storage = storage; _manager = manager; _logger = logger; var key = keys.FirstOrDefault().Value; StorageConnectionString = $"DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;" + $"AccountName={storage.Name};AccountKey={key}"; }
/// <summary> /// Get or create new storage in a resource group. /// </summary> /// <param name="service"></param> /// <param name="resourceGroup"></param> /// <param name="name"></param> /// <param name="addressSpace"></param> /// <param name="secure"></param> /// <returns></returns> public static async Task <INetworkResource> GetOrCreateAsync( this INetworkFactory service, IResourceGroupResource resourceGroup, string name, string addressSpace = null, bool secure = false) { var resource = await Try.Async(() => service.GetAsync(resourceGroup, name)); if (resource == null) { resource = await service.CreateAsync(resourceGroup, name, addressSpace, secure); } return(resource); }
/// <summary> /// Helper to create new client /// </summary> /// <returns></returns> private async Task <IotHubClient> CreateIoTHubClientAsync( IResourceGroupResource resourceGroup) { var environment = await resourceGroup.Subscription.GetAzureEnvironmentAsync(); var credentials = await _creds.GetTokenCredentialsAsync( environment.ManagementEndpoint); var client = new IotHubClient(credentials) { SubscriptionId = await resourceGroup.Subscription.GetSubscriptionId() }; return(client); }
/// <inheritdoc/> public async Task <INetworkResource> CreateAsync( IResourceGroupResource resourceGroup, string name, string addressSpace, bool secure) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (addressSpace == null) { addressSpace = "172.16.0.0/16"; } var client = await CreateClientAsync(resourceGroup); name = await client.Networks.SelectResourceNameAsync(resourceGroup.Name, "net", name); var region = await resourceGroup.Subscription.GetRegionAsync(); _logger.Information("Trying to create network {name}...", name); var nsg = await client.NetworkSecurityGroups .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .CreateAsync(); var networkDefinition = client.Networks .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .WithAddressSpace(addressSpace); if (secure) { networkDefinition = networkDefinition.DefineSubnet("subnet") .WithAddressPrefix(addressSpace) .WithExistingNetworkSecurityGroup(nsg) .Attach(); } var network = await networkDefinition.CreateAsync(); _logger.Information("Created network {name}.", name); return(new NetworkResource(this, resourceGroup, network, _logger)); }
/// <inheritdoc/> public async Task <INetworkResource> GetAsync( IResourceGroupResource resourceGroup, string name) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var client = await CreateClientAsync(resourceGroup); var network = await client.Networks.GetByResourceGroupAsync( resourceGroup.Name, name); if (network == null) { return(null); } return(new NetworkResource(this, resourceGroup, network, _logger)); }
/// <summary> /// Helper to create new client /// </summary> /// <returns></returns> protected async Task <IAzure> CreateClientAsync( IResourceGroupResource resourceGroup) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } var environment = await resourceGroup.Subscription.GetAzureEnvironmentAsync(); var subscriptionId = await resourceGroup.Subscription.GetSubscriptionId(); var credentials = await _creds.GetAzureCredentialsAsync(environment); return(Azure .Configure() .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic) .Authenticate(credentials) .WithSubscription(subscriptionId)); }
/// <summary> /// Create iot hub /// </summary> /// <param name="manager"></param> /// <param name="resourceGroup"></param> /// <param name="name"></param> /// <param name="properties"></param> /// <param name="rule"></param> /// <param name="logger"></param> public IoTHubResource(IoTHubFactory manager, IResourceGroupResource resourceGroup, string name, IotHubProperties properties, ILogger logger, SharedAccessSignatureAuthorizationRule rule) { _resourceGroup = resourceGroup; Name = name; _manager = manager; _properties = properties; _logger = logger; PrimaryConnectionString = ConnectionString.CreateServiceConnectionString( properties.HostName, rule.KeyName, rule.PrimaryKey).ToString(); SecondaryConnectionString = ConnectionString.CreateServiceConnectionString( properties.HostName, rule.KeyName, rule.SecondaryKey).ToString(); if (properties.EventHubEndpoints.TryGetValue("events", out var evtHub)) { EventHubConnectionString = ConnectionString.CreateEventHubConnectionString( evtHub.Endpoint, rule.KeyName, rule.PrimaryKey).ToString(); } }
/// <summary> /// Create a new linux virtual machine /// </summary> public static Task <IVirtualMachineResource> CreateAsync( this IVirtualMachineFactory service, IResourceGroupResource resourceGroup, string name, VirtualMachineImage image) => service.CreateAsync(resourceGroup, name, null, image, null);
/// <summary> /// Create a new randomly named storage /// </summary> public static Task <INetworkResource> CreateAsync( this INetworkFactory service, IResourceGroupResource resourceGroup) => service.CreateAsync(resourceGroup, null, null, false);
/// <summary> /// Get or create new ubuntu server 16.04 LTS vm in a resource group. /// </summary> /// <param name="service"></param> /// <param name="resourceGroup"></param> /// <param name="name"></param> /// <param name="network"></param> /// <returns></returns> public static Task <IVirtualMachineResource> GetOrCreateBionicAsync( this IVirtualMachineFactory service, IResourceGroupResource resourceGroup, string name, INetworkResource network = null) => service.GetOrCreateAsync(resourceGroup, name, network, KnownImages.Ubuntu_18_04_lts);
/// <inheritdoc/> public async Task <IIoTHubResource> CreateAsync( IResourceGroupResource resourceGroup, string hubName) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } var client = await CreateIoTHubClientAsync(resourceGroup); // Check quota var quota = await client.ResourceProviderCommon .GetSubscriptionQuotaAsync(); var limit = quota.Value .FirstOrDefault(x => x.Name.Value.Equals("paidIotHubCount")); if (limit?.Limit == limit?.CurrentValue) { throw new ExternalDependencyException( $"Subscription limit reached at {limit?.Limit ?? -1}"); } // Check name - null means we need to create one if (string.IsNullOrEmpty(hubName)) { while (true) { hubName = StringEx.CreateUnique(10, "iothub"); var result = client.IotHubResource.CheckNameAvailability( new OperationInputs { Name = hubName }); if (result.NameAvailable ?? false) { break; } } } else { var result = client.IotHubResource.CheckNameAvailability( new OperationInputs { Name = hubName }); if (!(result.NameAvailable ?? false)) { throw new ArgumentException("hub exists with this name", nameof(hubName)); } } // Create hub var hub = await client.IotHubResource.CreateOrUpdateAsync( resourceGroup.Name, hubName, new IotHubDescription { Location = await resourceGroup.Subscription.GetRegionAsync(), Sku = new IotHubSkuInfo { Name = IotHubSku.S1, Capacity = 1 }, Properties = new IotHubProperties { AuthorizationPolicies = new List <SharedAccessSignatureAuthorizationRule> { new SharedAccessSignatureAuthorizationRule( kIoTHubOwner, AccessRights.RegistryReadRegistryWriteServiceConnectDeviceConnect) } } }); _logger.Info($"Created iot hub {hubName} in resource " + $"group {resourceGroup.Name}..."); var keys = await client.IotHubResource.GetKeysForKeyNameAsync( resourceGroup.Name, hubName, kIoTHubOwner); return(new IoTHubResource(this, resourceGroup, hubName, hub.Properties, _logger, keys)); }
/// <inheritdoc/> public async Task <IVirtualMachineResource> CreateAsync( IResourceGroupResource resourceGroup, string name, INetworkResource netres, VirtualMachineImage image, string customData) { if (resourceGroup == null) { throw new ArgumentNullException(nameof(resourceGroup)); } var client = await CreateClientAsync(resourceGroup); name = await client.VirtualMachines.SelectResourceNameAsync(resourceGroup.Name, "vm", name); var user = VirtualMachineResource.kDefaultUser; var pw = "Vm$" + name.ToSha1Hash().Substring(0, 3); if (image == null) { image = KnownImages.Ubuntu_16_04_lts; } var attempt = 0; INetwork network = null; if (netres != null) { network = await client.Networks.GetByResourceGroupAsync( resourceGroup.Name, netres.Name); if (network == null) { throw new ArgumentException(nameof(netres)); } } var originalRegion = await resourceGroup.Subscription.GetRegionAsync(); while (true) { var regionAndVmSize = await SelectRegionAndVmSizeAsync( resourceGroup, client); if (regionAndVmSize == null) { throw new ExternalDependencyException( "No sizes available."); } var region = regionAndVmSize.Item1; var vmSize = regionAndVmSize.Item2; try { var nicDefine = client.NetworkInterfaces .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name); var nic = nicDefine .WithNewPrimaryNetwork(client.Networks .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .WithAddressSpace("172.16.0.0/16")) .WithPrimaryPrivateIPAddressDynamic(); var ipName = await client.PublicIPAddresses.SelectResourceNameAsync( resourceGroup.Name, "ip"); var publicIP = client.PublicIPAddresses .Define(ipName) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name); if (network != null && originalRegion == region) { nic = nicDefine .WithExistingPrimaryNetwork(network) .WithSubnet(netres.Subnet) .WithPrimaryPrivateIPAddressDynamic(); } nic = nic.WithNewPrimaryPublicIPAddress( client.PublicIPAddresses .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name)); var withOs = client.VirtualMachines .Define(name) .WithRegion(region) .WithExistingResourceGroup(resourceGroup.Name) .WithNewPrimaryNetworkInterface(nic); IWithFromImageCreateOptionsManaged machine; if (image.IsLinux) { machine = withOs .WithLatestLinuxImage(image.Publisher, image.Offer, image.Sku) .WithRootUsername(user) .WithRootPassword(pw); } else { machine = withOs .WithLatestWindowsImage(image.Publisher, image.Offer, image.Sku) .WithAdminUsername(user) .WithAdminPassword(pw); } _logger.Info($"Trying to create vm {name} on {vmSize}..."); IVirtualMachine vm = null; if (!string.IsNullOrEmpty(customData)) { vm = await machine .WithCustomData(customData) .WithSize(vmSize) .CreateAsync(); _logger.Info($"Starting vm {name} ..."); // Restart for changes to go into effect await vm.RestartAsync(); } else { vm = await machine.WithSize(vmSize).CreateAsync(); } _logger.Info($"Created vm {name}."); return(new VirtualMachineResource(this, resourceGroup, vm, user, pw, _logger)); } catch (Exception ex) { _logger.Info( $"#{attempt} failed creating VM {name} as {vmSize}...", () => ex); await TryDeleteResourcesAsync(resourceGroup, name); if (++attempt == 3) { throw ex; } } } }
/// <summary> /// Create a new randomly named storage /// </summary> public static Task <IStorageResource> CreateAsync( this IStorageFactory service, IResourceGroupResource resourceGroup) { return(service.CreateAsync(resourceGroup, null)); }