Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: azurerm_redis_enterprise_cluster & azurerm_redis_enterprise_database #10706

Merged
merged 12 commits into from
Feb 26, 2021
1 change: 1 addition & 0 deletions .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var services = mapOf(
"privatedns" to "Private DNS",
"recoveryservices" to "Recovery Services",
"redis" to "Redis",
"redisenterprise" to "Redis Enterprise",
"relay" to "Relay",
"resource" to "Resources",
"sql" to "SQL",
Expand Down
29 changes: 29 additions & 0 deletions azurerm/helpers/azure/error_output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package azure

import (
"fmt"
"strings"
)

// QuotedStringSlice formats a string slice into a quoted string containing all segments passed in a slice (e.g. string[]{"one", "two", "three"} will return {"one", "two" or "three"}). Useful for error messages with multiple possible values.
func QuotedStringSlice(strs []string) string {
if len(strs) == 1 {
return fmt.Sprint(`"`, strs[0], `"`)
}

var sb strings.Builder

for i, str := range strs {
if i < (len(strs) - 1) {
if i == (len(strs) - 2) {
sb.WriteString(fmt.Sprint(`"`, str, `"`))
} else {
sb.WriteString(fmt.Sprint(`"`, str, `", `))
}
} else {
sb.WriteString(fmt.Sprint(` or "`, str, `"`))
}
}

return sb.String()
}
36 changes: 36 additions & 0 deletions azurerm/helpers/azure/error_output_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package azure

import "testing"

func TestQuotedStringSlice(t *testing.T) {
testData := []struct {
input []string
expected string
}{
{
input: []string{""},
expected: `""`,
},
{
input: []string{"Din Djarin"},
expected: `"Din Djarin"`,
},
{
input: []string{"Baby Yoda", "Grogu"},
expected: `"Baby Yoda" or "Grogu"`,
},
{
input: []string{"This", "is", "the", "way"},
expected: `"This", "is", "the" or "way"`,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q..", v.input)

actual := QuotedStringSlice(v.input)
if v.expected != actual {
t.Fatalf("Expected %s but got %s", v.expected, actual)
}
}
}
3 changes: 3 additions & 0 deletions azurerm/internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import (
privatedns "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/privatedns/client"
recoveryServices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/recoveryservices/client"
redis "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/redis/client"
redisenterprise "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/redisenterprise/client"
relay "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/relay/client"
resource "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/client"
search "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/search/client"
Expand Down Expand Up @@ -170,6 +171,7 @@ type Client struct {
PrivateDns *privatedns.Client
RecoveryServices *recoveryServices.Client
Redis *redis.Client
RedisEnterprise *redisenterprise.Client
Relay *relay.Client
Resource *resource.Client
Search *search.Client
Expand Down Expand Up @@ -267,6 +269,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.PrivateDns = privatedns.NewClient(o)
client.RecoveryServices = recoveryServices.NewClient(o)
client.Redis = redis.NewClient(o)
client.RedisEnterprise = redisenterprise.NewClient(o)
client.Relay = relay.NewClient(o)
client.Resource = resource.NewClient(o)
client.Search = search.NewClient(o)
Expand Down
2 changes: 2 additions & 0 deletions azurerm/internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/privatedns"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/recoveryservices"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/redis"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/redisenterprise"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/relay"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/search"
Expand Down Expand Up @@ -169,6 +170,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration {
privatedns.Registration{},
recoveryservices.Registration{},
redis.Registration{},
redisenterprise.Registration{},
relay.Registration{},
resource.Registration{},
search.Registration{},
Expand Down
29 changes: 29 additions & 0 deletions azurerm/internal/services/redisenterprise/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/redisenterprise/mgmt/2021-03-01/redisenterprise"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

type Client struct {
Client *redisenterprise.Client
DatabaseClient *redisenterprise.DatabasesClient
OperationsClient *redisenterprise.OperationsClient
}

func NewClient(o *common.ClientOptions) *Client {
client := redisenterprise.NewClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)

databaseClient := redisenterprise.NewDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&databaseClient.Client, o.ResourceManagerAuthorizer)

operationsClient := redisenterprise.NewOperationsClient(o.ResourceManagerEndpoint)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)

return &Client{
Client: &client,
DatabaseClient: &databaseClient,
OperationsClient: &operationsClient,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type RedisEnterpriseClusterId struct {
SubscriptionId string
ResourceGroup string
RedisEnterpriseName string
}

func NewRedisEnterpriseClusterID(subscriptionId, resourceGroup, redisEnterpriseName string) RedisEnterpriseClusterId {
return RedisEnterpriseClusterId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
RedisEnterpriseName: redisEnterpriseName,
}
}

func (id RedisEnterpriseClusterId) String() string {
segments := []string{
fmt.Sprintf("Redis Enterprise Name %q", id.RedisEnterpriseName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Redis Enterprise Cluster", segmentsStr)
}

func (id RedisEnterpriseClusterId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Cache/redisEnterprise/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.RedisEnterpriseName)
}

// RedisEnterpriseClusterID parses a RedisEnterpriseCluster ID into an RedisEnterpriseClusterId struct
func RedisEnterpriseClusterID(input string) (*RedisEnterpriseClusterId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := RedisEnterpriseClusterId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.ResourceGroup == "" {
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
}

if resourceId.RedisEnterpriseName, err = id.PopSegment("redisEnterprise"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package parse

import (
"fmt"
"strconv"
"strings"
)

// RedisEnterpriseCacheSku type
type RedisEnterpriseCacheSku struct {
Name string
Capacity string
}

// RedisEnterpriseCacheSkuName parses the input string into a RedisEnterpriseCacheSku type
func RedisEnterpriseCacheSkuName(input string) (*RedisEnterpriseCacheSku, error) {
if len(strings.TrimSpace(input)) == 0 {
return nil, fmt.Errorf("unable to parse Redis Enterprise Cluster 'sku_name' %q", input)
}

skuParts := strings.Split(input, "-")

if len(skuParts) < 2 {
return nil, fmt.Errorf("invalid Redis Enterprise Cluster 'sku_name', got %q", input)
}

if strings.TrimSpace(skuParts[0]) == "" {
return nil, fmt.Errorf("invalid Redis Enterprise Cluster 'sku_name' missing 'name' segment, got %q", input)
}

if strings.TrimSpace(skuParts[1]) == "" {
return nil, fmt.Errorf("invalid Redis Enterprise Cluster 'sku_name' missing 'capacity' segment, got %q", input)
}

_, err := strconv.ParseInt(skuParts[1], 10, 32)
if err != nil {
return nil, fmt.Errorf("invalid Redis Enterprise Cluster 'sku_name', 'capacity' segment must be of type int32 and be a valid int32 value, got %q", skuParts[1])
}

redisEnterpriseCacheSku := RedisEnterpriseCacheSku{
Name: skuParts[0],
Capacity: skuParts[1],
}

return &redisEnterpriseCacheSku, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package parse

import (
"testing"
)

func TestRedisenterpriseSkuName(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *RedisEnterpriseCacheSku
}{
{
// empty
Input: "",
Error: true,
},
{
// missing sku name and capacity
Input: "-",
Error: true,
},
{
// missing sku name and capacity with multi delimiter
Input: "--",
Error: true,
},
{
// missing sku name
Input: "-1",
Error: true,
},
{
// missing capacity
Input: "Sku1-",
Error: true,
},
{
// invalid capacity type
Input: "Sku1-A",
Error: true,
},
{
// invalid capacity above int32 type
Input: "Sku1-2147483648",
Error: true,
},
{
// valid with ignored extra delimiter
Input: "skuName-1-",
Expected: &RedisEnterpriseCacheSku{
Name: "skuName",
Capacity: "1",
},
},
{
// valid
Input: "skuName-1",
Expected: &RedisEnterpriseCacheSku{
Name: "skuName",
Capacity: "1",
},
},
{
// upper-cased
Input: "SKUNAME-1",
Expected: &RedisEnterpriseCacheSku{
Name: "SKUNAME",
Capacity: "1",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := RedisEnterpriseCacheSkuName(v.Input)
if err != nil {
if v.Error {
continue
}
t.Fatalf("Expected a value but got an error: %s", err)
}

if actual.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}

if actual.Capacity != v.Expected.Capacity {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}
Loading