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

saving cosmosdb keys as secrets #935

Merged
merged 18 commits into from
Apr 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 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 Down
4 changes: 4 additions & 0 deletions config/samples/azure_v1alpha1_cosmosdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ spec:
resourceGroup: resourcegroup-azure-operators
properties:
databaseAccountOfferType: Standard

# Use the field below to optionally specify a different keyvault
# to store the connectiong string secrets in
#keyVaultToStoreSecrets: asoSecretKeyVault
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")
jpflueger marked this conversation as resolved.
Show resolved Hide resolved

}

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
56 changes: 38 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,10 +44,10 @@ func (*AzureCosmosDBManager) CreateOrUpdateCosmosDB(
location string,
kind v1alpha1.CosmosDBKind,
dbType v1alpha1.CosmosDBDatabaseAccountOfferType,
tags map[string]*string) (*documentdb.DatabaseAccount, *errhelp.AzureError) {
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)
Expand Down Expand Up @@ -91,13 +93,13 @@ func (*AzureCosmosDBManager) CreateOrUpdateCosmosDB(

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 +108,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 +141,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, 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