|
Add this skill
npx mdskills install sickn33/azure-resource-manager-redis-dotnetComprehensive Azure Redis management SDK skill with excellent examples and clear separation of concerns
1---2name: azure-resource-manager-redis-dotnet3description: |4 Azure Resource Manager SDK for Redis in .NET. Use for MANAGEMENT PLANE operations: creating/managing Azure Cache for Redis instances, firewall rules, access keys, patch schedules, linked servers (geo-replication), and private endpoints via Azure Resource Manager. NOT for data plane operations (get/set keys, pub/sub) - use StackExchange.Redis for that. Triggers: "Redis cache", "create Redis", "manage Redis", "ARM Redis", "RedisResource", "provision Redis", "Azure Cache for Redis".5package: Azure.ResourceManager.Redis6---78# Azure.ResourceManager.Redis (.NET)910Management plane SDK for provisioning and managing Azure Cache for Redis resources via Azure Resource Manager.1112> **⚠️ Management vs Data Plane**13> - **This SDK (Azure.ResourceManager.Redis)**: Create caches, configure firewall rules, manage access keys, set up geo-replication14> - **Data Plane SDK (StackExchange.Redis)**: Get/set keys, pub/sub, streams, Lua scripts1516## Installation1718```bash19dotnet add package Azure.ResourceManager.Redis20dotnet add package Azure.Identity21```2223**Current Version**: 1.5.1 (Stable)24**API Version**: 2024-11-0125**Target Frameworks**: .NET 8.0, .NET Standard 2.02627## Environment Variables2829```bash30AZURE_SUBSCRIPTION_ID=<your-subscription-id>31# For service principal auth (optional)32AZURE_TENANT_ID=<tenant-id>33AZURE_CLIENT_ID=<client-id>34AZURE_CLIENT_SECRET=<client-secret>35```3637## Authentication3839```csharp40using Azure.Identity;41using Azure.ResourceManager;42using Azure.ResourceManager.Redis;4344// Always use DefaultAzureCredential45var credential = new DefaultAzureCredential();46var armClient = new ArmClient(credential);4748// Get subscription49var subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID");50var subscription = armClient.GetSubscriptionResource(51 new ResourceIdentifier($"/subscriptions/{subscriptionId}"));52```5354## Resource Hierarchy5556```57ArmClient58└── SubscriptionResource59 └── ResourceGroupResource60 └── RedisResource61 ├── RedisFirewallRuleResource62 ├── RedisPatchScheduleResource63 ├── RedisLinkedServerWithPropertyResource64 ├── RedisPrivateEndpointConnectionResource65 └── RedisCacheAccessPolicyResource66```6768## Core Workflows6970### 1. Create Redis Cache7172```csharp73using Azure.ResourceManager.Redis;74using Azure.ResourceManager.Redis.Models;7576// Get resource group77var resourceGroup = await subscription78 .GetResourceGroupAsync("my-resource-group");7980// Define cache configuration81var cacheData = new RedisCreateOrUpdateContent(82 location: AzureLocation.EastUS,83 sku: new RedisSku(RedisSkuName.Standard, RedisSkuFamily.BasicOrStandard, 1))84{85 EnableNonSslPort = false,86 MinimumTlsVersion = RedisTlsVersion.Tls1_2,87 RedisConfiguration = new RedisCommonConfiguration88 {89 MaxMemoryPolicy = "volatile-lru"90 },91 Tags =92 {93 ["environment"] = "production"94 }95};9697// Create cache (long-running operation)98var cacheCollection = resourceGroup.Value.GetAllRedis();99var operation = await cacheCollection.CreateOrUpdateAsync(100 WaitUntil.Completed,101 "my-redis-cache",102 cacheData);103104RedisResource cache = operation.Value;105Console.WriteLine($"Cache created: {cache.Data.HostName}");106```107108### 2. Get Redis Cache109110```csharp111// Get existing cache112var cache = await resourceGroup.Value113 .GetRedisAsync("my-redis-cache");114115Console.WriteLine($"Host: {cache.Value.Data.HostName}");116Console.WriteLine($"Port: {cache.Value.Data.Port}");117Console.WriteLine($"SSL Port: {cache.Value.Data.SslPort}");118Console.WriteLine($"Provisioning State: {cache.Value.Data.ProvisioningState}");119```120121### 3. Update Redis Cache122123```csharp124var patchData = new RedisPatch125{126 Sku = new RedisSku(RedisSkuName.Standard, RedisSkuFamily.BasicOrStandard, 2),127 RedisConfiguration = new RedisCommonConfiguration128 {129 MaxMemoryPolicy = "allkeys-lru"130 }131};132133var updateOperation = await cache.Value.UpdateAsync(134 WaitUntil.Completed,135 patchData);136```137138### 4. Delete Redis Cache139140```csharp141await cache.Value.DeleteAsync(WaitUntil.Completed);142```143144### 5. Get Access Keys145146```csharp147var keys = await cache.Value.GetKeysAsync();148Console.WriteLine($"Primary Key: {keys.Value.PrimaryKey}");149Console.WriteLine($"Secondary Key: {keys.Value.SecondaryKey}");150```151152### 6. Regenerate Access Keys153154```csharp155var regenerateContent = new RedisRegenerateKeyContent(RedisRegenerateKeyType.Primary);156var newKeys = await cache.Value.RegenerateKeyAsync(regenerateContent);157Console.WriteLine($"New Primary Key: {newKeys.Value.PrimaryKey}");158```159160### 7. Manage Firewall Rules161162```csharp163// Create firewall rule164var firewallData = new RedisFirewallRuleData(165 startIP: System.Net.IPAddress.Parse("10.0.0.1"),166 endIP: System.Net.IPAddress.Parse("10.0.0.255"));167168var firewallCollection = cache.Value.GetRedisFirewallRules();169var firewallOperation = await firewallCollection.CreateOrUpdateAsync(170 WaitUntil.Completed,171 "allow-internal-network",172 firewallData);173174// List all firewall rules175await foreach (var rule in firewallCollection.GetAllAsync())176{177 Console.WriteLine($"Rule: {rule.Data.Name} ({rule.Data.StartIP} - {rule.Data.EndIP})");178}179180// Delete firewall rule181var ruleToDelete = await firewallCollection.GetAsync("allow-internal-network");182await ruleToDelete.Value.DeleteAsync(WaitUntil.Completed);183```184185### 8. Configure Patch Schedule (Premium SKU)186187```csharp188// Patch schedules require Premium SKU189var scheduleData = new RedisPatchScheduleData(190 new[]191 {192 new RedisPatchScheduleSetting(RedisDayOfWeek.Saturday, 2) // 2 AM Saturday193 {194 MaintenanceWindow = TimeSpan.FromHours(5)195 },196 new RedisPatchScheduleSetting(RedisDayOfWeek.Sunday, 2) // 2 AM Sunday197 {198 MaintenanceWindow = TimeSpan.FromHours(5)199 }200 });201202var scheduleCollection = cache.Value.GetRedisPatchSchedules();203await scheduleCollection.CreateOrUpdateAsync(204 WaitUntil.Completed,205 RedisPatchScheduleDefaultName.Default,206 scheduleData);207```208209### 9. Import/Export Data (Premium SKU)210211```csharp212// Import data from blob storage213var importContent = new ImportRdbContent(214 files: new[] { "https://mystorageaccount.blob.core.windows.net/container/dump.rdb" },215 format: "RDB");216217await cache.Value.ImportDataAsync(WaitUntil.Completed, importContent);218219// Export data to blob storage220var exportContent = new ExportRdbContent(221 prefix: "backup",222 container: "https://mystorageaccount.blob.core.windows.net/container?sastoken",223 format: "RDB");224225await cache.Value.ExportDataAsync(WaitUntil.Completed, exportContent);226```227228### 10. Force Reboot229230```csharp231var rebootContent = new RedisRebootContent232{233 RebootType = RedisRebootType.AllNodes,234 ShardId = 0 // For clustered caches235};236237await cache.Value.ForceRebootAsync(rebootContent);238```239240## SKU Reference241242| SKU | Family | Capacity | Features |243|-----|--------|----------|----------|244| Basic | C | 0-6 | Single node, no SLA, dev/test only |245| Standard | C | 0-6 | Two nodes (primary/replica), SLA |246| Premium | P | 1-5 | Clustering, geo-replication, VNet, persistence |247248**Capacity Sizes (Family C - Basic/Standard)**:249- C0: 250 MB250- C1: 1 GB251- C2: 2.5 GB252- C3: 6 GB253- C4: 13 GB254- C5: 26 GB255- C6: 53 GB256257**Capacity Sizes (Family P - Premium)**:258- P1: 6 GB per shard259- P2: 13 GB per shard260- P3: 26 GB per shard261- P4: 53 GB per shard262- P5: 120 GB per shard263264## Key Types Reference265266| Type | Purpose |267|------|---------|268| `ArmClient` | Entry point for all ARM operations |269| `RedisResource` | Represents a Redis cache instance |270| `RedisCollection` | Collection for cache CRUD operations |271| `RedisFirewallRuleResource` | Firewall rule for IP filtering |272| `RedisPatchScheduleResource` | Maintenance window configuration |273| `RedisLinkedServerWithPropertyResource` | Geo-replication linked server |274| `RedisPrivateEndpointConnectionResource` | Private endpoint connection |275| `RedisCacheAccessPolicyResource` | RBAC access policy |276| `RedisCreateOrUpdateContent` | Cache creation payload |277| `RedisPatch` | Cache update payload |278| `RedisSku` | SKU configuration (name, family, capacity) |279| `RedisAccessKeys` | Primary and secondary access keys |280| `RedisRegenerateKeyContent` | Key regeneration request |281282## Best Practices2832841. **Use `WaitUntil.Completed`** for operations that must finish before proceeding2852. **Use `WaitUntil.Started`** when you want to poll manually or run operations in parallel2863. **Always use `DefaultAzureCredential`** — never hardcode keys2874. **Handle `RequestFailedException`** for ARM API errors2885. **Use `CreateOrUpdateAsync`** for idempotent operations2896. **Navigate hierarchy** via `Get*` methods (e.g., `cache.GetRedisFirewallRules()`)2907. **Use Premium SKU** for production workloads requiring geo-replication, clustering, or persistence2918. **Enable TLS 1.2 minimum** — set `MinimumTlsVersion = RedisTlsVersion.Tls1_2`2929. **Disable non-SSL port** — set `EnableNonSslPort = false` for security29310. **Rotate keys regularly** — use `RegenerateKeyAsync` and update connection strings294295## Error Handling296297```csharp298using Azure;299300try301{302 var operation = await cacheCollection.CreateOrUpdateAsync(303 WaitUntil.Completed, cacheName, cacheData);304}305catch (RequestFailedException ex) when (ex.Status == 409)306{307 Console.WriteLine("Cache already exists");308}309catch (RequestFailedException ex) when (ex.Status == 400)310{311 Console.WriteLine($"Invalid configuration: {ex.Message}");312}313catch (RequestFailedException ex)314{315 Console.WriteLine($"ARM Error: {ex.Status} - {ex.ErrorCode}: {ex.Message}");316}317```318319## Common Pitfalls3203211. **SKU downgrades not allowed** — You cannot downgrade from Premium to Standard/Basic3222. **Clustering requires Premium** — Shard configuration only available on Premium SKU3233. **Geo-replication requires Premium** — Linked servers only work with Premium caches3244. **VNet injection requires Premium** — Virtual network support is Premium-only3255. **Patch schedules require Premium** — Maintenance windows only configurable on Premium3266. **Cache name globally unique** — Redis cache names must be unique across all Azure subscriptions3277. **Long provisioning times** — Cache creation can take 15-20 minutes; use `WaitUntil.Started` for async patterns328329## Connecting with StackExchange.Redis (Data Plane)330331After creating the cache with this management SDK, use StackExchange.Redis for data operations:332333```csharp334using StackExchange.Redis;335336// Get connection info from management SDK337var cache = await resourceGroup.Value.GetRedisAsync("my-redis-cache");338var keys = await cache.Value.GetKeysAsync();339340// Connect with StackExchange.Redis341var connectionString = $"{cache.Value.Data.HostName}:{cache.Value.Data.SslPort},password={keys.Value.PrimaryKey},ssl=True,abortConnect=False";342var connection = ConnectionMultiplexer.Connect(connectionString);343var db = connection.GetDatabase();344345// Data operations346await db.StringSetAsync("key", "value");347var value = await db.StringGetAsync("key");348```349350## Related SDKs351352| SDK | Purpose | Install |353|-----|---------|---------|354| `StackExchange.Redis` | Data plane (get/set, pub/sub, streams) | `dotnet add package StackExchange.Redis` |355| `Azure.ResourceManager.Redis` | Management plane (this SDK) | `dotnet add package Azure.ResourceManager.Redis` |356| `Microsoft.Azure.StackExchangeRedis` | Azure-specific Redis extensions | `dotnet add package Microsoft.Azure.StackExchangeRedis` |357
Full transparency — inspect the skill content before installing.