Skip to content

Commit

Permalink
Merge pull request #29 from Azure/master
Browse files Browse the repository at this point in the history
pr
  • Loading branch information
WilliamMortlMicrosoft authored Apr 20, 2020
2 parents 5fe07e6 + b98e0b9 commit ffae6f5
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 156 deletions.
10 changes: 6 additions & 4 deletions api/v1alpha1/cosmosdb_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ type CosmosDBSpec struct {

// +kubebuilder:validation:MinLength=0

Location string `json:"location,omitempty"`
ResourceGroup string `json:"resourceGroup"`
Kind CosmosDBKind `json:"kind,omitempty"`
Properties CosmosDBProperties `json:"properties,omitempty"`
Location string `json:"location,omitempty"`
ResourceGroup string `json:"resourceGroup"`
Kind CosmosDBKind `json:"kind,omitempty"`
Properties CosmosDBProperties `json:"properties,omitempty"`
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
}

// CosmosDBKind enumerates the values for kind.
Expand All @@ -42,6 +43,7 @@ type CosmosDBProperties struct {
// CosmosDBDatabaseAccountOfferType - The offer type for the Cosmos DB database account.
DatabaseAccountOfferType CosmosDBDatabaseAccountOfferType `json:"databaseAccountOfferType,omitempty"`
//Locations []CosmosDBLocation `json:"locations,omitempty"`
MongoDBVersion string `json:"mongoDBVersion,omitempty"`
}

// +kubebuilder:validation:Enum=Standard
Expand Down
7 changes: 7 additions & 0 deletions config/samples/azure_v1alpha1_cosmosdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ spec:
resourceGroup: resourcegroup-azure-operators
properties:
databaseAccountOfferType: Standard
# optionally set the mongoDBVersion to "3.2" or "3.6", if omitted the default is "3.2"
# NOTE: kind must be set to MongoDB for this to take effect
#mongoDBVersion: "3.6"

# Use the field below to optionally specify a different keyvault
# to store the connectiong string secrets in
#keyVaultToStoreSecrets: asoSecretKeyVault
16 changes: 8 additions & 8 deletions config/samples/azure_v1alpha1_storageaccount.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ spec:
accessTier: Hot
supportsHttpsTrafficOnly: true
# Optional: networkRule
networkRule:
bypass: AzureServices # Possible values are AzureServices, Metrics, None, Logging
defaultAction: Deny # Possible values are Allow, Deny
virtualNetworkRules:
- subnetId: /subscriptions/{subscription}/resourceGroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}
ipRules: #could be an ip range or a ip address
- ipAddressOrRange: 2.2.0.0/24
- ipAddressOrRange: 2.2.2.1
# networkRule:
# bypass: AzureServices # Possible values are AzureServices, Metrics, None, Logging
# defaultAction: Deny # Possible values are Allow, Deny
# virtualNetworkRules:
# - subnetId: /subscriptions/{subscription}/resourceGroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}
# ipRules: #could be an ip range or a ip address
# - ipAddressOrRange: 2.2.0.0/24
# - ipAddressOrRange: 2.2.2.1
29 changes: 22 additions & 7 deletions controllers/cosmosdb_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,27 @@ import (
"testing"

"github.com/Azure/azure-service-operator/api/v1alpha1"
"github.com/Azure/azure-service-operator/pkg/errhelp"

"github.com/stretchr/testify/assert"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

func TestCosmosDBHappyPath(t *testing.T) {
t.Parallel()
defer PanicRecover(t)
ctx := context.Background()
assert := assert.New(t)

cosmosDBAccountName := GenerateTestResourceNameWithRandom("cosmosdb", 8)
cosmosDBNamespace := "default"
name := GenerateTestResourceNameWithRandom("cosmosdb", 8)
namespace := "default"

dbInstance := &v1alpha1.CosmosDB{
ObjectMeta: metav1.ObjectMeta{
Name: cosmosDBAccountName,
Namespace: cosmosDBNamespace,
Name: name,
Namespace: namespace,
},
Spec: v1alpha1.CosmosDBSpec{
Location: tc.resourceGroupLocation,
Expand All @@ -37,10 +42,22 @@ func TestCosmosDBHappyPath(t *testing.T) {
},
}

key := types.NamespacedName{Name: name, Namespace: namespace}

EnsureInstance(ctx, t, tc, dbInstance)

assert.Eventually(func() bool {
secret, err := tc.secretClient.Get(ctx, key)
return err == nil && len(secret) > 0
}, tc.timeoutFast, tc.retry, "wait for cosmosdb to have secret")

EnsureDelete(ctx, t, tc, dbInstance)

assert.Eventually(func() bool {
_, err := tc.secretClient.Get(ctx, key)
return err != nil
}, tc.timeoutFast, tc.retry, "wait for cosmosdb to delete secret")

}

func TestCosmosDBControllerNoResourceGroup(t *testing.T) {
Expand Down Expand Up @@ -69,10 +86,8 @@ func TestCosmosDBControllerNoResourceGroup(t *testing.T) {
},
},
}
//the expected error meessage to be shown
errMessage := "Waiting for resource group '" + resourceGroupName + "' to be available"

EnsureInstanceWithResult(ctx, t, tc, dbInstance1, errMessage, false)
EnsureInstanceWithResult(ctx, t, tc, dbInstance1, errhelp.ResourceGroupNotFoundErrorCode, false)
EnsureDelete(ctx, t, tc, dbInstance1)
}

Expand Down
2 changes: 1 addition & 1 deletion controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func setup() error {
secretClient,
scheme.Scheme,
)
cosmosDbManager = resourcemanagercosmosdb.NewAzureCosmosDBManager()
cosmosDbManager = resourcemanagercosmosdb.NewAzureCosmosDBManager(secretClient)
apiMgmtManager = resourcemanagerapimgmt.NewManager()
resourceGroupManager = resourcegroupsresourcemanager.NewAzureResourceGroupManager()
eventHubManagers = resourcemanagereventhub.AzureEventHubManagers
Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ func main() {
)
eventhubNamespaceClient := resourcemanagereventhub.NewEventHubNamespaceClient()
consumerGroupClient := resourcemanagereventhub.NewConsumerGroupClient()
cosmosDBClient := resourcemanagercosmosdb.NewAzureCosmosDBManager(
secretClient,
)
storageManagers := resourcemanagerstorage.AzureStorageManagers
keyVaultManager := resourcemanagerkeyvault.NewAzureKeyVaultManager(mgr.GetScheme())
keyVaultKeyManager := &resourcemanagerkeyvault.KeyvaultKeyClient{
Expand Down Expand Up @@ -172,7 +175,7 @@ func main() {
err = (&controllers.CosmosDBReconciler{
Reconciler: &controllers.AsyncReconciler{
Client: mgr.GetClient(),
AzureClient: resourcemanagercosmosdb.NewAzureCosmosDBManager(),
AzureClient: cosmosDBClient,
Telemetry: telemetry.InitializeTelemetryDefault(
"CosmosDB",
ctrl.Log.WithName("controllers").WithName("CosmosDB"),
Expand Down
1 change: 1 addition & 0 deletions pkg/errhelp/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
NotFoundErrorCode = "NotFound"
NoSuchHost = "no such host"
ParentNotFoundErrorCode = "ParentResourceNotFound"
PreconditionFailed = "PreconditionFailed"
QuotaExceeded = "QuotaExceeded"
ResourceGroupNotFoundErrorCode = "ResourceGroupNotFound"
RegionDoesNotAllowProvisioning = "RegionDoesNotAllowProvisioning"
Expand Down
67 changes: 49 additions & 18 deletions pkg/resourcemanager/cosmosdbs/cosmosdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import (

"github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb"
"github.com/Azure/azure-service-operator/api/v1alpha1"
"github.com/Azure/azure-service-operator/pkg/errhelp"
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
"github.com/Azure/azure-service-operator/pkg/resourcemanager/iam"
"github.com/Azure/azure-service-operator/pkg/secrets"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
)

// AzureCosmosDBManager is the struct which contains helper functions for resource groups
type AzureCosmosDBManager struct{}
type AzureCosmosDBManager struct {
SecretClient secrets.SecretClient
}

func getCosmosDBClient() (documentdb.DatabaseAccountsClient, error) {
cosmosDBClient := documentdb.NewDatabaseAccountsClientWithBaseURI(config.BaseURI(), config.SubscriptionID())
Expand All @@ -28,9 +30,9 @@ func getCosmosDBClient() (documentdb.DatabaseAccountsClient, error) {
cosmosDBClient = documentdb.DatabaseAccountsClient{}
} else {
cosmosDBClient.Authorizer = a
cosmosDBClient.AddToUserAgent(config.UserAgent())
}

err = cosmosDBClient.AddToUserAgent(config.UserAgent())
return cosmosDBClient, err
}

Expand All @@ -42,15 +44,25 @@ func (*AzureCosmosDBManager) CreateOrUpdateCosmosDB(
location string,
kind v1alpha1.CosmosDBKind,
dbType v1alpha1.CosmosDBDatabaseAccountOfferType,
tags map[string]*string) (*documentdb.DatabaseAccount, *errhelp.AzureError) {
dbVersion string,
tags map[string]*string) (*documentdb.DatabaseAccount, error) {
cosmosDBClient, err := getCosmosDBClient()
if err != nil {
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}

dbKind := documentdb.DatabaseAccountKind(kind)
sDBType := string(dbType)

var capabilities []documentdb.Capability
if dbKind == documentdb.MongoDB && dbVersion == "3.6" {
capabilities = []documentdb.Capability{
{Name: to.StringPtr("EnableMongo")},
}
} else {
capabilities = make([]documentdb.Capability, 0)
}

/*
* Current state of Locations and CosmosDB properties:
* Creating a Database account with CosmosDB requires
Expand Down Expand Up @@ -84,20 +96,21 @@ func (*AzureCosmosDBManager) CreateOrUpdateCosmosDB(
EnableMultipleWriteLocations: to.BoolPtr(false),
IsVirtualNetworkFilterEnabled: to.BoolPtr(false),
Locations: &locationsArray,
Capabilities: &capabilities,
},
}
createUpdateFuture, err := cosmosDBClient.CreateOrUpdate(
ctx, groupName, cosmosDBName, createUpdateParams)

if err != nil {
// initial create request failed, wrap error
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}

result, err := createUpdateFuture.Result(cosmosDBClient)
if err != nil {
// there is no immediate result, wrap error
return &result, errhelp.NewAzureErrorAzureError(err)
return &result, err
}
return &result, nil
}
Expand All @@ -106,31 +119,31 @@ func (*AzureCosmosDBManager) CreateOrUpdateCosmosDB(
func (*AzureCosmosDBManager) GetCosmosDB(
ctx context.Context,
groupName string,
cosmosDBName string) (*documentdb.DatabaseAccount, *errhelp.AzureError) {
cosmosDBName string) (*documentdb.DatabaseAccount, error) {
cosmosDBClient, err := getCosmosDBClient()
if err != nil {
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}

result, err := cosmosDBClient.Get(ctx, groupName, cosmosDBName)
if err != nil {
return &result, errhelp.NewAzureErrorAzureError(err)
return &result, err
}
return &result, nil
}

// CheckNameExistsCosmosDB checks if the global account name already exists
func (*AzureCosmosDBManager) CheckNameExistsCosmosDB(
ctx context.Context,
accountName string) (bool, *errhelp.AzureError) {
accountName string) (bool, error) {
cosmosDBClient, err := getCosmosDBClient()
if err != nil {
return false, errhelp.NewAzureErrorAzureError(err)
return false, err
}

response, err := cosmosDBClient.CheckNameExists(ctx, accountName)
if err != nil {
return false, errhelp.NewAzureErrorAzureError(err)
return false, err
}

switch response.StatusCode {
Expand All @@ -139,28 +152,46 @@ func (*AzureCosmosDBManager) CheckNameExistsCosmosDB(
case http.StatusOK:
return true, nil
default:
return false, errhelp.NewAzureErrorAzureError(fmt.Errorf("unhandled status code for CheckNameExists"))
return false, fmt.Errorf("unhandled status code for CheckNameExists")
}
}

// DeleteCosmosDB removes the resource group named by env var
func (*AzureCosmosDBManager) DeleteCosmosDB(
ctx context.Context,
groupName string,
cosmosDBName string) (*autorest.Response, *errhelp.AzureError) {
cosmosDBName string) (*autorest.Response, error) {
cosmosDBClient, err := getCosmosDBClient()
if err != nil {
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}

deleteFuture, err := cosmosDBClient.Delete(ctx, groupName, cosmosDBName)
if err != nil {
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}

ar, err := deleteFuture.Result(cosmosDBClient)
if err != nil {
return nil, errhelp.NewAzureErrorAzureError(err)
return nil, err
}
return &ar, nil
}

// ListKeys lists the read & write keys for a database account
func (*AzureCosmosDBManager) ListKeys(
ctx context.Context,
groupName string,
accountName string) (*documentdb.DatabaseAccountListKeysResult, error) {
client, err := getCosmosDBClient()
if err != nil {
return nil, err
}

result, err := client.ListKeys(ctx, groupName, accountName)
if err != nil {
return nil, err
}

return &result, nil
}
17 changes: 10 additions & 7 deletions pkg/resourcemanager/cosmosdbs/cosmosdb_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,32 @@ import (

"github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb"
"github.com/Azure/azure-service-operator/api/v1alpha1"
"github.com/Azure/azure-service-operator/pkg/errhelp"
"github.com/Azure/azure-service-operator/pkg/resourcemanager"
"github.com/Azure/azure-service-operator/pkg/secrets"
"github.com/Azure/go-autorest/autorest"
)

// NewAzureCosmosDBManager creates a new cosmos db client
func NewAzureCosmosDBManager() *AzureCosmosDBManager {
return &AzureCosmosDBManager{}
func NewAzureCosmosDBManager(secretClient secrets.SecretClient) *AzureCosmosDBManager {
return &AzureCosmosDBManager{secretClient}
}

// CosmosDBManager client functions
type CosmosDBManager interface {
// CreateOrUpdateCosmosDB creates a new cosmos database account
CreateOrUpdateCosmosDB(ctx context.Context, groupName string, cosmosDBName string, location string, kind v1alpha1.CosmosDBKind, dbType v1alpha1.CosmosDBDatabaseAccountOfferType, tags map[string]*string) (*documentdb.DatabaseAccount, *errhelp.AzureError)
CreateOrUpdateCosmosDB(ctx context.Context, groupName string, cosmosDBName string, location string, kind v1alpha1.CosmosDBKind, dbType v1alpha1.CosmosDBDatabaseAccountOfferType, dbVersion string, tags map[string]*string) (*documentdb.DatabaseAccount, error)

// GetCosmosDB gets a cosmos database account
GetCosmosDB(ctx context.Context, groupName string, cosmosDBName string) (*documentdb.DatabaseAccount, *errhelp.AzureError)
GetCosmosDB(ctx context.Context, groupName string, cosmosDBName string) (*documentdb.DatabaseAccount, error)

// DeleteCosmosDB removes the cosmos database account
DeleteCosmosDB(ctx context.Context, groupName string, cosmosDBName string) (*autorest.Response, *errhelp.AzureError)
DeleteCosmosDB(ctx context.Context, groupName string, cosmosDBName string) (*autorest.Response, error)

// CheckNameExistsCosmosDB check if the account name already exists globally
CheckNameExistsCosmosDB(ctx context.Context, accountName string) (bool, *errhelp.AzureError)
CheckNameExistsCosmosDB(ctx context.Context, accountName string) (bool, error)

// ListKeys lists the read & write keys for a database account
ListKeys(ctx context.Context, groupName string, accountName string) (*documentdb.DatabaseAccountListKeysResult, error)

resourcemanager.ARMClient
}
Loading

0 comments on commit ffae6f5

Please sign in to comment.