Add support for subscriptionID on AzureSQL types (#2910)
This commit is contained in:
Родитель
a02d3ecd03
Коммит
a93ed945f1
|
@ -20,6 +20,7 @@ type AzureSqlActionSpec struct {
|
|||
ResourceGroup string `json:"resourceGroup"`
|
||||
ActionName string `json:"actionName"`
|
||||
ServerName string `json:"serverName"`
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
ServerAdminSecretName string `json:"serverAdminSecretName,omitempty"`
|
||||
ServerSecretKeyVault string `json:"serverSecretKeyVault,omitempty"`
|
||||
UserSecretKeyVault string `json:"userSecretKeyVault,omitempty"`
|
||||
|
|
|
@ -31,6 +31,8 @@ type AzureSQLManagedUserSpec struct {
|
|||
// +kubebuilder:validation:Required
|
||||
Roles []string `json:"roles"`
|
||||
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
|
||||
ManagedIdentityName string `json:"managedIdentityName,omitempty"`
|
||||
ManagedIdentityClientId string `json:"managedIdentityClientId"`
|
||||
KeyVaultSecretPrefix string `json:"keyVaultSecretPrefix,omitempty"`
|
||||
|
|
|
@ -32,6 +32,7 @@ type AzureSQLUserSpec struct {
|
|||
Roles []string `json:"roles"`
|
||||
|
||||
// optional
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
AdminSecret string `json:"adminSecret,omitempty"`
|
||||
AdminSecretKeyVault string `json:"adminSecretKeyVault,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
|
|
|
@ -19,6 +19,7 @@ type AzureSQLVNetRuleSpec struct {
|
|||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Required
|
||||
Server string `json:"server"`
|
||||
ServerSubscriptionID string `json:"serverSubscriptionID,omitempty"`
|
||||
VNetResourceGroup string `json:"vNetResourceGroup"`
|
||||
VNetName string `json:"vNetName"`
|
||||
SubnetName string `json:"subnetName"`
|
||||
|
|
|
@ -104,7 +104,7 @@ type CosmosDBList struct {
|
|||
Items []CosmosDB `json:"items"`
|
||||
}
|
||||
|
||||
//CosmosDBVirtualNetworkRule virtual Network ACL Rule object
|
||||
// CosmosDBVirtualNetworkRule virtual Network ACL Rule object
|
||||
type CosmosDBVirtualNetworkRule struct {
|
||||
// ID - Resource ID of a subnet, for example: /subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName}.
|
||||
SubnetID *string `json:"subnetID,omitempty"`
|
||||
|
|
|
@ -28,7 +28,7 @@ type EventhubSpec struct {
|
|||
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
|
||||
}
|
||||
|
||||
//EventhubAuthorizationRule defines the name and rights of the access policy
|
||||
// EventhubAuthorizationRule defines the name and rights of the access policy
|
||||
type EventhubAuthorizationRule struct {
|
||||
// Name - Name of AuthorizationRule for eventhub
|
||||
Name string `json:"name,omitempty"`
|
||||
|
@ -36,7 +36,7 @@ type EventhubAuthorizationRule struct {
|
|||
Rights []string `json:"rights,omitempty"`
|
||||
}
|
||||
|
||||
//EventHubStorageAccount contains details of the eventhub storage account
|
||||
// EventHubStorageAccount contains details of the eventhub storage account
|
||||
type EventHubStorageAccount struct {
|
||||
// ResourceGroup - Name of the storage account resource group
|
||||
// +kubebuilder:validation:Pattern=^[-\w\._\(\)]+$
|
||||
|
@ -49,7 +49,7 @@ type EventHubStorageAccount struct {
|
|||
AccountName string `json:"accountName,omitempty"`
|
||||
}
|
||||
|
||||
//Destination for capture (blob storage etc)
|
||||
// Destination for capture (blob storage etc)
|
||||
type Destination struct {
|
||||
// ArchiveNameFormat - Blob naming convention for archive, e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}. Here all the parameters (Namespace,EventHub .. etc) are mandatory irrespective of order
|
||||
ArchiveNameFormat string `json:"archiveNameFormat,omitempty"`
|
||||
|
@ -62,7 +62,7 @@ type Destination struct {
|
|||
StorageAccount EventHubStorageAccount `json:"storageAccount,omitempty"`
|
||||
}
|
||||
|
||||
//CaptureDescription defines the properties required for eventhub capture
|
||||
// CaptureDescription defines the properties required for eventhub capture
|
||||
type CaptureDescription struct {
|
||||
// Destination - Resource id of the storage account to be used to create the blobs
|
||||
Destination Destination `json:"destination,omitempty"`
|
||||
|
@ -78,7 +78,7 @@ type CaptureDescription struct {
|
|||
IntervalInSeconds int32 `json:"intervalInSeconds,omitempty"`
|
||||
}
|
||||
|
||||
//EventhubProperties defines the namespace properties
|
||||
// EventhubProperties defines the namespace properties
|
||||
type EventhubProperties struct {
|
||||
// +kubebuilder:validation:Maximum=7
|
||||
// +kubebuilder:validation:Minimum=1
|
||||
|
|
|
@ -55,14 +55,14 @@ type EventhubNamespaceSku struct {
|
|||
Capacity int32 `json:"capacity,omitempty"` //allowedValues 1, 2, 4
|
||||
}
|
||||
|
||||
//EventhubNamespaceProperties defines the namespace properties
|
||||
// EventhubNamespaceProperties defines the namespace properties
|
||||
type EventhubNamespaceProperties struct {
|
||||
IsAutoInflateEnabled bool `json:"isAutoInflateEnabled,omitempty"`
|
||||
MaximumThroughputUnits int32 `json:"maximumThroughputUnits,omitempty"`
|
||||
KafkaEnabled bool `json:"kafkaEnabled,omitempty"`
|
||||
}
|
||||
|
||||
//EventhubNamespaceNetworkRule defines the namespace network rule
|
||||
// EventhubNamespaceNetworkRule defines the namespace network rule
|
||||
type EventhubNamespaceNetworkRule struct {
|
||||
DefaultAction DefaultAction `json:"defaultAction,omitempty"`
|
||||
// VirtualNetworkRules - List VirtualNetwork Rules
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
helpers "github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
)
|
||||
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
@ -66,6 +67,7 @@ type AzureSqlDatabaseSpec struct {
|
|||
Server string `json:"server"`
|
||||
|
||||
// +kubebuilder:validation:Optional
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
Edition DBEdition `json:"edition"` // TODO: Remove this in v1beta2
|
||||
Sku *SqlDatabaseSku `json:"sku,omitempty"` // TODO: make this required in v1beta2
|
||||
MaxSize *resource.Quantity `json:"maxSize,omitempty"`
|
||||
|
|
|
@ -32,15 +32,19 @@ type AzureSqlFailoverGroupSpec struct {
|
|||
ResourceGroup string `json:"resourceGroup"`
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Required
|
||||
Server string `json:"server"`
|
||||
Server string `json:"server"`
|
||||
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
|
||||
FailoverPolicy ReadWriteEndpointFailoverPolicy `json:"failoverPolicy"`
|
||||
// TODO: This field should be a ptr as it must not be specified if the failover policy is Manual,
|
||||
// TODO: but is required when the policy is Automatic
|
||||
FailoverGracePeriod int32 `json:"failoverGracePeriod"`
|
||||
SecondaryServer string `json:"secondaryServer"`
|
||||
SecondaryServerResourceGroup string `json:"secondaryServerResourceGroup"`
|
||||
DatabaseList []string `json:"databaseList"`
|
||||
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
|
||||
FailoverGracePeriod int32 `json:"failoverGracePeriod"`
|
||||
SecondaryServer string `json:"secondaryServer"`
|
||||
SecondaryServerResourceGroup string `json:"secondaryServerResourceGroup"`
|
||||
SecondaryServerSubscriptionID string `json:"SecondaryServerSubscriptionId,omitempty"`
|
||||
DatabaseList []string `json:"databaseList"`
|
||||
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
@ -22,6 +22,7 @@ type AzureSqlFirewallRuleSpec struct {
|
|||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Required
|
||||
Server string `json:"server"`
|
||||
SubscriptionID string `json:"subscriptionID,omitempty"`
|
||||
StartIPAddress string `json:"startIpAddress,omitempty"`
|
||||
EndIPAddress string `json:"endIpAddress,omitempty"`
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ type AzureSqlServerSpec struct {
|
|||
// +kubebuilder:validation:Pattern=^[-\w\._\(\)]+$
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:Required
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
|
||||
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//go:build all || azuresqlserver || azuresqlservercombined
|
||||
// +build all azuresqlserver azuresqlservercombined
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/Azure/azure-service-operator/api/v1beta1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
"github.com/Azure/azure-service-operator/pkg/secrets"
|
||||
)
|
||||
|
||||
func TestAzureSqlServerCombinedHappyPathCrossSub(t *testing.T) {
|
||||
t.Skip("Skipping as we don't currently have 2 Subscriptions for CI")
|
||||
// For this test to pass, remove the t.Skip above and ensure that the identity you are testing with has contributor
|
||||
// access to both the primary CI sub and the secondary subscription below.
|
||||
// You must also manually create the "test-aso-rg" resourceGroup
|
||||
secondSubscription := "82acd5bb-4206-47d4-9c12-a65db028483d"
|
||||
secondSubscriptionResourceGroupName := "test-aso-rg"
|
||||
|
||||
t.Parallel()
|
||||
defer PanicRecover(t)
|
||||
ctx := context.Background()
|
||||
require := require.New(t)
|
||||
var err error
|
||||
|
||||
// Add any setup steps that needs to be executed before each test
|
||||
rgName := tc.resourceGroupName
|
||||
sqlServerName := GenerateTestResourceNameWithRandom("sqlserver", 10)
|
||||
rgLocation := "westus3"
|
||||
rgLocation2 := "southcentralus"
|
||||
sqlServerTwoName := GenerateTestResourceNameWithRandom("sqlserver-two", 10)
|
||||
|
||||
sqlServerNamespacedName := types.NamespacedName{Name: sqlServerName, Namespace: "default"}
|
||||
sqlServerNamespacedName2 := types.NamespacedName{Name: sqlServerTwoName, Namespace: "default"}
|
||||
|
||||
// Create the SqlServer object and expect the Reconcile to be created
|
||||
sqlServerInstance := v1beta1.NewAzureSQLServer(sqlServerNamespacedName, secondSubscriptionResourceGroupName, rgLocation)
|
||||
sqlServerInstance.Spec.SubscriptionID = secondSubscription
|
||||
|
||||
// Send request for 2nd server (failovergroup test) before waiting on first server
|
||||
sqlServerInstance2 := v1beta1.NewAzureSQLServer(sqlServerNamespacedName2, rgName, rgLocation2)
|
||||
|
||||
// create and wait
|
||||
RequireInstance(ctx, t, tc, sqlServerInstance)
|
||||
RequireInstance(ctx, t, tc, sqlServerInstance2)
|
||||
|
||||
sqlDatabaseName1 := GenerateTestResourceNameWithRandom("sqldatabase", 10)
|
||||
sqlDatabaseName3 := GenerateTestResourceNameWithRandom("sqldatabase", 10)
|
||||
var sqlDatabaseInstance1 *v1beta1.AzureSqlDatabase
|
||||
var sqlDatabaseInstance3 *v1beta1.AzureSqlDatabase
|
||||
|
||||
sqlFirewallRuleNamespacedNameLocal := types.NamespacedName{
|
||||
Name: GenerateTestResourceNameWithRandom("sqlfwr-local", 10),
|
||||
Namespace: "default",
|
||||
}
|
||||
sqlFirewallRuleNamespacedNameRemote := types.NamespacedName{
|
||||
Name: GenerateTestResourceNameWithRandom("sqlfwr-remote", 10),
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var sqlFirewallRuleInstanceLocal *v1beta1.AzureSqlFirewallRule
|
||||
var sqlFirewallRuleInstanceRemote *v1beta1.AzureSqlFirewallRule
|
||||
|
||||
// Create the SqlDatabase object and expect the Reconcile to be created
|
||||
sqlDatabaseInstance1 = &v1beta1.AzureSqlDatabase{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: sqlDatabaseName1,
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1beta1.AzureSqlDatabaseSpec{
|
||||
Location: rgLocation,
|
||||
ResourceGroup: secondSubscriptionResourceGroupName,
|
||||
Server: sqlServerName,
|
||||
SubscriptionID: secondSubscription,
|
||||
Edition: 0,
|
||||
},
|
||||
}
|
||||
|
||||
EnsureInstance(ctx, t, tc, sqlDatabaseInstance1)
|
||||
|
||||
// run sub tests that require 1 sql server ----------------------------------
|
||||
t.Run("group1", func(t *testing.T) {
|
||||
// Create a database in the new server
|
||||
t.Run("set up database with short and long term retention", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the SqlDatabase object and expect the Reconcile to be created
|
||||
sqlDatabaseInstance3 = &v1beta1.AzureSqlDatabase{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: sqlDatabaseName3,
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1beta1.AzureSqlDatabaseSpec{
|
||||
Location: rgLocation,
|
||||
ResourceGroup: secondSubscriptionResourceGroupName,
|
||||
Server: sqlServerName,
|
||||
SubscriptionID: secondSubscription,
|
||||
Sku: &v1beta1.SqlDatabaseSku{
|
||||
Name: "S0",
|
||||
Tier: "Standard",
|
||||
},
|
||||
WeeklyRetention: "P3W",
|
||||
ShortTermRetentionPolicy: &v1beta1.SQLDatabaseShortTermRetentionPolicy{
|
||||
RetentionDays: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
EnsureInstance(ctx, t, tc, sqlDatabaseInstance3)
|
||||
|
||||
// Now update with an invalid retention policy
|
||||
sqlDatabaseInstance3.Spec.ShortTermRetentionPolicy.RetentionDays = -1
|
||||
err = tc.k8sClient.Update(ctx, sqlDatabaseInstance3)
|
||||
require.Equal(nil, err, "updating sql database in k8s")
|
||||
|
||||
namespacedName := types.NamespacedName{Name: sqlDatabaseName3, Namespace: "default"}
|
||||
require.Eventually(func() bool {
|
||||
db := &v1beta1.AzureSqlDatabase{}
|
||||
err = tc.k8sClient.Get(ctx, namespacedName, db)
|
||||
require.Equal(nil, err, "err getting DB from k8s")
|
||||
return db.Status.Provisioned == false && strings.Contains(db.Status.Message, errhelp.BackupRetentionPolicyInvalid)
|
||||
}, tc.timeout, tc.retry, "wait for sql database to be updated in k8s")
|
||||
})
|
||||
|
||||
// Create FirewallRules ---------------------------------------
|
||||
|
||||
t.Run("set up wide range firewall rule in primary server", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the SqlFirewallRule object and expect the Reconcile to be created
|
||||
sqlFirewallRuleInstanceLocal = v1beta1.NewAzureSQLFirewallRule(
|
||||
sqlFirewallRuleNamespacedNameLocal,
|
||||
secondSubscriptionResourceGroupName,
|
||||
sqlServerName,
|
||||
"1.1.1.1",
|
||||
"255.255.255.255",
|
||||
)
|
||||
sqlFirewallRuleInstanceLocal.Spec.SubscriptionID = secondSubscription
|
||||
|
||||
EnsureInstance(ctx, t, tc, sqlFirewallRuleInstanceLocal)
|
||||
})
|
||||
|
||||
t.Run("set up azure only firewall rule in primary server", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the SqlFirewallRule object and expect the Reconcile to be created
|
||||
sqlFirewallRuleInstanceRemote = v1beta1.NewAzureSQLFirewallRule(
|
||||
sqlFirewallRuleNamespacedNameRemote,
|
||||
secondSubscriptionResourceGroupName,
|
||||
sqlServerName,
|
||||
"0.0.0.0",
|
||||
"0.0.0.0",
|
||||
)
|
||||
sqlFirewallRuleInstanceRemote.Spec.SubscriptionID = secondSubscription
|
||||
|
||||
EnsureInstance(ctx, t, tc, sqlFirewallRuleInstanceRemote)
|
||||
})
|
||||
})
|
||||
|
||||
var sqlFailoverGroupInstance *v1beta1.AzureSqlFailoverGroup
|
||||
sqlFailoverGroupName := GenerateTestResourceNameWithRandom("sqlfog-dev", 10)
|
||||
|
||||
sqlFailoverGroupNamespacedName := types.NamespacedName{Name: sqlFailoverGroupName, Namespace: "default"}
|
||||
|
||||
t.Run("group3", func(t *testing.T) {
|
||||
t.Run("delete local firewallrule", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlFirewallRuleInstanceLocal)
|
||||
})
|
||||
|
||||
t.Run("delete remote firewallrule", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlFirewallRuleInstanceRemote)
|
||||
})
|
||||
|
||||
t.Run("create failovergroup", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the SqlFailoverGroup object and expect the Reconcile to be created
|
||||
sqlFailoverGroupInstance = &v1beta1.AzureSqlFailoverGroup{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: sqlFailoverGroupNamespacedName.Name,
|
||||
Namespace: sqlFailoverGroupNamespacedName.Namespace,
|
||||
},
|
||||
Spec: v1beta1.AzureSqlFailoverGroupSpec{
|
||||
Location: rgLocation,
|
||||
ResourceGroup: secondSubscriptionResourceGroupName,
|
||||
Server: sqlServerName,
|
||||
SubscriptionID: secondSubscription,
|
||||
FailoverPolicy: v1beta1.FailoverPolicyAutomatic,
|
||||
FailoverGracePeriod: 60,
|
||||
SecondaryServer: sqlServerTwoName,
|
||||
SecondaryServerResourceGroup: rgName,
|
||||
DatabaseList: []string{sqlDatabaseName1},
|
||||
},
|
||||
}
|
||||
|
||||
EnsureInstance(ctx, t, tc, sqlFailoverGroupInstance)
|
||||
|
||||
// verify secret has been created
|
||||
require.Eventually(func() bool {
|
||||
key := secrets.SecretKey{Name: sqlFailoverGroupInstance.Name, Namespace: sqlFailoverGroupInstance.Namespace, Kind: "AzureSqlFailoverGroup"}
|
||||
secrets, err := tc.secretClient.Get(ctx, key)
|
||||
|
||||
return err == nil && strings.Contains(string(secrets["azureSqlPrimaryServer"]), sqlServerName)
|
||||
}, tc.timeout, tc.retry, "wait for secret store to show failovergroup server names ")
|
||||
|
||||
sqlFailoverGroupInstance.Spec.FailoverPolicy = v1beta1.FailoverPolicyManual
|
||||
sqlFailoverGroupInstance.Spec.FailoverGracePeriod = 0 // GracePeriod cannot be set when policy is manual
|
||||
|
||||
err = tc.k8sClient.Update(ctx, sqlFailoverGroupInstance)
|
||||
require.Equal(nil, err, "updating sql failover group in k8s")
|
||||
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(config.GlobalCredentials().WithSubscriptionID(secondSubscription))
|
||||
require.Equal(nil, err, "getting failovergroup client")
|
||||
|
||||
require.Eventually(func() bool {
|
||||
fog, err := failoverGroupsClient.Get(ctx, secondSubscriptionResourceGroupName, sqlServerName, sqlFailoverGroupName)
|
||||
require.Equal(nil, err, "err getting failover group from Azure")
|
||||
return fog.ReadWriteEndpoint.FailoverPolicy == sql.Manual
|
||||
}, tc.timeout, tc.retry, "wait for sql failover group failover policy to be updated in Azure")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("group4", func(t *testing.T) {
|
||||
t.Run("delete failovergroup", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlFailoverGroupInstance)
|
||||
})
|
||||
t.Run("delete dbs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlDatabaseInstance1)
|
||||
EnsureDelete(ctx, t, tc, sqlDatabaseInstance3)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("group5", func(t *testing.T) {
|
||||
t.Run("delete sqlServerInstance", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlServerInstance)
|
||||
})
|
||||
t.Run("delete sqlServerInstance2", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
EnsureDelete(ctx, t, tc, sqlServerInstance2)
|
||||
})
|
||||
})
|
||||
}
|
|
@ -140,19 +140,19 @@ func TestAzureSqlServerCombinedHappyPath(t *testing.T) {
|
|||
}, tc.timeout, tc.retry, "wait for sql database to be updated in k8s")
|
||||
|
||||
require.Eventually(func() bool {
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, rgName, sqlServerName, sqlDatabaseName2)
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, "", rgName, sqlServerName, sqlDatabaseName2)
|
||||
require.Equal(nil, err, "err getting DB fromAzure")
|
||||
return db.Sku != nil && db.Sku.Name != nil && *db.Sku.Name == "Basic"
|
||||
}, tc.timeout, tc.retry, "wait for sql database Sku.Name to be updated in azure")
|
||||
|
||||
require.Eventually(func() bool {
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, rgName, sqlServerName, sqlDatabaseName2)
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, "", rgName, sqlServerName, sqlDatabaseName2)
|
||||
require.Equal(nil, err, "err getting DB fromAzure")
|
||||
return db.Sku != nil && db.Sku.Tier != nil && *db.Sku.Tier == "Basic"
|
||||
}, tc.timeout, tc.retry, "wait for sql database Sku.Tier to be updated in azure")
|
||||
|
||||
require.Eventually(func() bool {
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, rgName, sqlServerName, sqlDatabaseName2)
|
||||
db, err := tc.sqlDbManager.GetDB(ctx, "", rgName, sqlServerName, sqlDatabaseName2)
|
||||
require.Equal(nil, err, "err getting DB fromAzure")
|
||||
return db.MaxSizeBytes != nil && *db.MaxSizeBytes == int64(maxSizeMb)*int64(1024)*int64(1024)
|
||||
}, tc.timeout, tc.retry, "wait for sql database MaxSizeBytes to be updated in azure")
|
||||
|
|
|
@ -19,7 +19,7 @@ type ConsumerGroupReconciler struct {
|
|||
// +kubebuilder:rbac:groups=azure.microsoft.com,resources=consumergroups,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=azure.microsoft.com,resources={consumergroups/status,consumergroups/finalizers},verbs=get;update;patch
|
||||
|
||||
//Reconcile reconciler for consumergroup
|
||||
// Reconcile reconciler for consumergroup
|
||||
func (r *ConsumerGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
return r.Reconciler.Reconcile(ctx, req, &azurev1alpha1.ConsumerGroup{})
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ type EventhubNamespaceReconciler struct {
|
|||
// +kubebuilder:rbac:groups=azure.microsoft.com,resources=eventhubnamespaces,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=azure.microsoft.com,resources={eventhubnamespaces/status,eventhubnamespaces/finalizers},verbs=get;update;patch
|
||||
|
||||
//Reconcile reconciler for eventhubnamespace
|
||||
// Reconcile reconciler for eventhubnamespace
|
||||
func (r *EventhubNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
return r.Reconciler.Reconcile(ctx, req, &azurev1alpha1.EventhubNamespace{})
|
||||
}
|
||||
|
||||
//SetupWithManager sets up the functions for the controller
|
||||
// SetupWithManager sets up the functions for the controller
|
||||
func (r *EventhubNamespaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&azurev1alpha1.EventhubNamespace{}).
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
//test Postgre SQL server unhappy path
|
||||
// test Postgre SQL server unhappy path
|
||||
func TestPSQLServerControllerNoResourceGroup(t *testing.T) {
|
||||
t.Parallel()
|
||||
defer PanicRecover(t)
|
||||
|
|
|
@ -49,6 +49,7 @@ func StripErrorTimes(err string) string {
|
|||
// - Unrecoverable errors are fatal. When returned to the async_reconciler reconciliation is stopped until
|
||||
// a new modification is made to the resource in question. This is useful for things like client errors that
|
||||
// no amount of reconciliation will fix.
|
||||
//
|
||||
// If an error is not in the allowed list and also not in the unrecoverable list, it is classified as nonfatal,
|
||||
// but an error is returned. When returned to the async_reconciler, reconciliation will continue but an error will
|
||||
// be logged.
|
||||
|
|
|
@ -111,11 +111,18 @@ func (s *AzureSqlActionManager) UpdateUserPassword(
|
|||
|
||||
// UpdateAdminPassword gets the server instance from Azure, updates the admin password
|
||||
// for the server and stores the new password in the secret
|
||||
func (s *AzureSqlActionManager) UpdateAdminPassword(ctx context.Context, groupName string, serverName string, secretKey secrets.SecretKey, secretClient secrets.SecretClient) error {
|
||||
func (s *AzureSqlActionManager) UpdateAdminPassword(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
groupName string,
|
||||
serverName string,
|
||||
secretKey secrets.SecretKey,
|
||||
secretClient secrets.SecretClient,
|
||||
) error {
|
||||
|
||||
azuresqlserverManager := azuresqlserver.NewAzureSqlServerManager(s.Creds, secretClient, s.Scheme)
|
||||
// Get the SQL server instance
|
||||
server, err := azuresqlserverManager.GetServer(ctx, groupName, serverName)
|
||||
server, err := azuresqlserverManager.GetServer(ctx, subscriptionID, groupName, serverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -137,7 +144,15 @@ func (s *AzureSqlActionManager) UpdateAdminPassword(ctx context.Context, groupNa
|
|||
azureSqlServerProperties.AdministratorLoginPassword = to.StringPtr(newPassword)
|
||||
|
||||
// Update the SQL server with the newly generated password
|
||||
_, _, err = azuresqlserverManager.CreateOrUpdateSQLServer(ctx, groupName, *server.Location, serverName, server.Tags, azureSqlServerProperties, true)
|
||||
_, _, err = azuresqlserverManager.CreateOrUpdateSQLServer(
|
||||
ctx,
|
||||
subscriptionID,
|
||||
groupName,
|
||||
*server.Location,
|
||||
serverName,
|
||||
server.Tags,
|
||||
azureSqlServerProperties,
|
||||
true)
|
||||
|
||||
if err != nil {
|
||||
azerr := errhelp.NewAzureError(err)
|
||||
|
|
|
@ -32,6 +32,7 @@ func (s *AzureSqlActionManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
var userSecretClient secrets.SecretClient
|
||||
serverName := instance.Spec.ServerName
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
|
||||
if strings.ToLower(instance.Spec.ActionName) == "rolladmincreds" {
|
||||
if !instance.Status.Provisioned {
|
||||
|
@ -62,7 +63,7 @@ func (s *AzureSqlActionManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
}
|
||||
|
||||
// Roll SQL server's admin password
|
||||
err := s.UpdateAdminPassword(ctx, groupName, serverName, adminSecretKey, adminSecretClient)
|
||||
err := s.UpdateAdminPassword(ctx, subscriptionID, groupName, serverName, adminSecretKey, adminSecretClient)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
catch := []string{
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/Azure/azure-service-operator/api/v1beta1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
azuresqlshared "github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
|
@ -31,8 +31,8 @@ func NewAzureSqlDbManager(creds config.Credentials) *AzureSqlDbManager {
|
|||
}
|
||||
|
||||
// GetServer returns a SQL server
|
||||
func (m *AzureSqlDbManager) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.creds)
|
||||
func (m *AzureSqlDbManager) GetServer(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Server{}, err
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ func (m *AzureSqlDbManager) GetServer(ctx context.Context, resourceGroupName str
|
|||
}
|
||||
|
||||
// GetDB retrieves a database
|
||||
func (m *AzureSqlDbManager) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(m.creds)
|
||||
func (m *AzureSqlDbManager) GetDB(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Database{}, err
|
||||
}
|
||||
|
@ -62,18 +62,19 @@ func (m *AzureSqlDbManager) GetDB(ctx context.Context, resourceGroupName string,
|
|||
// DeleteDB deletes a DB
|
||||
func (m *AzureSqlDbManager) DeleteDB(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string) (future *sql.DatabasesDeleteFuture, err error) {
|
||||
|
||||
// check to see if the server exists, if it doesn't then short-circuit
|
||||
server, err := m.GetServer(ctx, resourceGroupName, serverName)
|
||||
server, err := m.GetServer(ctx, subscriptionID, resourceGroupName, serverName)
|
||||
if err != nil || *server.State != "Ready" {
|
||||
return nil, ignoreNotFound(err)
|
||||
}
|
||||
|
||||
// check to see if the db exists, if it doesn't then short-circuit
|
||||
db, err := m.GetDB(ctx, resourceGroupName, serverName, databaseName)
|
||||
db, err := m.GetDB(ctx, subscriptionID, resourceGroupName, serverName, databaseName)
|
||||
if err != nil {
|
||||
return nil, ignoreNotFound(err)
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ func (m *AzureSqlDbManager) DeleteDB(
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(m.creds)
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -104,13 +105,14 @@ func (m *AzureSqlDbManager) DeleteDB(
|
|||
// CreateOrUpdateDB creates or updates a DB in Azure
|
||||
func (m *AzureSqlDbManager) CreateOrUpdateDB(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
location string,
|
||||
serverName string,
|
||||
tags map[string]*string,
|
||||
properties azuresqlshared.SQLDatabaseProperties) (string, *sql.Database, error) {
|
||||
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(m.creds)
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -142,12 +144,13 @@ func (m *AzureSqlDbManager) CreateOrUpdateDB(
|
|||
// AddLongTermRetention enables / disables long term retention
|
||||
func (m *AzureSqlDbManager) AddLongTermRetention(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string,
|
||||
policy azuresqlshared.SQLDatabaseBackupLongTermRetentionPolicy) (*sql.BackupLongTermRetentionPoliciesCreateOrUpdateFuture, error) {
|
||||
|
||||
longTermClient, err := azuresqlshared.GetBackupLongTermRetentionPoliciesClient(m.creds)
|
||||
longTermClient, err := azuresqlshared.GetBackupLongTermRetentionPoliciesClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -202,12 +205,13 @@ func (m *AzureSqlDbManager) AddLongTermRetention(
|
|||
|
||||
func (m *AzureSqlDbManager) AddShortTermRetention(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string,
|
||||
policy *v1beta1.SQLDatabaseShortTermRetentionPolicy) (*sql.BackupShortTermRetentionPoliciesCreateOrUpdateFuture, error) {
|
||||
|
||||
client, err := azuresqlshared.GetBackupShortTermRetentionPoliciesClient(m.creds)
|
||||
client, err := azuresqlshared.GetBackupShortTermRetentionPoliciesClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't create BackupShortTermRetentionPoliciesClient")
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
// SqlDbManager is the client for the resource manager for SQL databases
|
||||
type SqlDbManager interface {
|
||||
CreateOrUpdateDB(ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
location string,
|
||||
serverName string,
|
||||
|
@ -22,19 +23,23 @@ type SqlDbManager interface {
|
|||
properties azuresqlshared.SQLDatabaseProperties) (pollingUrl string, db *sql.Database, err error)
|
||||
|
||||
DeleteDB(ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string) (future *sql.DatabasesDeleteFuture, err error)
|
||||
|
||||
GetDB(ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string, databaseName string) (sql.Database, error)
|
||||
|
||||
GetServer(ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string) (result sql.Server, err error)
|
||||
|
||||
AddLongTermRetention(ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string,
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager"
|
||||
azuresqlshared "github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/pollclient"
|
||||
)
|
||||
|
||||
|
@ -37,6 +37,7 @@ func (db *AzureSqlDbManager) Ensure(ctx context.Context, obj runtime.Object, opt
|
|||
return true, nil
|
||||
}
|
||||
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
location := instance.Spec.Location
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
server := instance.Spec.Server
|
||||
|
@ -109,10 +110,12 @@ func (db *AzureSqlDbManager) Ensure(ctx context.Context, obj runtime.Object, opt
|
|||
// No point in checking the status of the DB if our spec hashes don't match,
|
||||
// just seek to new target and check later
|
||||
if hash == instance.Status.SpecHash {
|
||||
dbGet, err := db.GetDB(ctx, groupName, server, dbName)
|
||||
dbGet, err := db.GetDB(ctx, subscriptionID, groupName, server, dbName)
|
||||
if err == nil {
|
||||
// optionally set the long term retention policy
|
||||
_, err = db.AddLongTermRetention(ctx,
|
||||
_, err = db.AddLongTermRetention(
|
||||
ctx,
|
||||
subscriptionID,
|
||||
groupName,
|
||||
server,
|
||||
dbName,
|
||||
|
@ -139,6 +142,7 @@ func (db *AzureSqlDbManager) Ensure(ctx context.Context, obj runtime.Object, opt
|
|||
|
||||
_, err = db.AddShortTermRetention(
|
||||
ctx,
|
||||
subscriptionID,
|
||||
groupName,
|
||||
server,
|
||||
dbName,
|
||||
|
@ -177,7 +181,7 @@ func (db *AzureSqlDbManager) Ensure(ctx context.Context, obj runtime.Object, opt
|
|||
}
|
||||
}
|
||||
}
|
||||
pollingUrl, _, err := db.CreateOrUpdateDB(ctx, groupName, location, server, labels, azureSQLDatabaseProperties)
|
||||
pollingUrl, _, err := db.CreateOrUpdateDB(ctx, subscriptionID, groupName, location, server, labels, azureSQLDatabaseProperties)
|
||||
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
|
@ -237,11 +241,12 @@ func (db *AzureSqlDbManager) Delete(ctx context.Context, obj runtime.Object, opt
|
|||
return false, err
|
||||
}
|
||||
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
server := instance.Spec.Server
|
||||
dbName := instance.ObjectMeta.Name
|
||||
|
||||
_, err = db.DeleteDB(ctx, groupName, server, dbName)
|
||||
_, err = db.DeleteDB(ctx, subscriptionID, groupName, server, dbName)
|
||||
if err != nil {
|
||||
azerr := errhelp.NewAzureError(err)
|
||||
if isIncompleteOp(azerr) {
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"context"
|
||||
"net/http"
|
||||
|
||||
sql "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/Azure/azure-service-operator/api/v1beta1"
|
||||
azuresqlshared "github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
"github.com/Azure/azure-service-operator/pkg/secrets"
|
||||
)
|
||||
|
@ -32,8 +32,8 @@ func NewAzureSqlFailoverGroupManager(creds config.Credentials, secretClient secr
|
|||
}
|
||||
|
||||
// GetServer returns a SQL server
|
||||
func (m *AzureSqlFailoverGroupManager) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.Creds)
|
||||
func (m *AzureSqlFailoverGroupManager) GetServer(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Server{}, err
|
||||
}
|
||||
|
@ -46,8 +46,14 @@ func (m *AzureSqlFailoverGroupManager) GetServer(ctx context.Context, resourceGr
|
|||
}
|
||||
|
||||
// GetDB retrieves a database
|
||||
func (m *AzureSqlFailoverGroupManager) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(m.Creds)
|
||||
func (m *AzureSqlFailoverGroupManager) GetDB(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
databaseName string,
|
||||
) (sql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Database{}, err
|
||||
}
|
||||
|
@ -62,8 +68,14 @@ func (m *AzureSqlFailoverGroupManager) GetDB(ctx context.Context, resourceGroupN
|
|||
|
||||
// TODO: Delete this?
|
||||
// GetFailoverGroup retrieves a failover group
|
||||
func (m *AzureSqlFailoverGroupManager) GetFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string) (sql.FailoverGroup, error) {
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(m.Creds)
|
||||
func (m *AzureSqlFailoverGroupManager) GetFailoverGroup(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
failovergroupname string,
|
||||
) (sql.FailoverGroup, error) {
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.FailoverGroup{}, err
|
||||
}
|
||||
|
@ -77,7 +89,14 @@ func (m *AzureSqlFailoverGroupManager) GetFailoverGroup(ctx context.Context, res
|
|||
}
|
||||
|
||||
// DeleteFailoverGroup deletes a failover group
|
||||
func (m *AzureSqlFailoverGroupManager) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) {
|
||||
func (m *AzureSqlFailoverGroupManager) DeleteFailoverGroup(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
failoverGroupName string,
|
||||
) (result autorest.Response, err error) {
|
||||
|
||||
result = autorest.Response{
|
||||
Response: &http.Response{
|
||||
StatusCode: 200,
|
||||
|
@ -85,12 +104,12 @@ func (m *AzureSqlFailoverGroupManager) DeleteFailoverGroup(ctx context.Context,
|
|||
}
|
||||
|
||||
// check to see if the server exists, if it doesn't then short-circuit
|
||||
_, err = m.GetServer(ctx, resourceGroupName, serverName)
|
||||
_, err = m.GetServer(ctx, subscriptionID, resourceGroupName, serverName)
|
||||
if err != nil {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(m.Creds)
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
@ -117,7 +136,7 @@ func (m *AzureSqlFailoverGroupManager) DeleteFailoverGroup(ctx context.Context,
|
|||
// TransformToSQLFailoverGroup translates the Kubernetes shaped v1beta1.AzureSqlFailoverGroup into the Azure SDK sql.FailoverGroup.
|
||||
// This function makes a number of remote calls and so should be called sparingly.
|
||||
func (m *AzureSqlFailoverGroupManager) TransformToSQLFailoverGroup(ctx context.Context, instance *v1beta1.AzureSqlFailoverGroup) (sql.FailoverGroup, error) {
|
||||
secondaryServer, err := m.GetServer(ctx, instance.Spec.SecondaryServerResourceGroup, instance.Spec.SecondaryServer)
|
||||
secondaryServer, err := m.GetServer(ctx, instance.Spec.SecondaryServerSubscriptionID, instance.Spec.SecondaryServerResourceGroup, instance.Spec.SecondaryServer)
|
||||
if err != nil {
|
||||
return sql.FailoverGroup{}, err
|
||||
}
|
||||
|
@ -134,7 +153,7 @@ func (m *AzureSqlFailoverGroupManager) TransformToSQLFailoverGroup(ctx context.C
|
|||
|
||||
// Parse the Databases in the Databaselist and form array of Resource IDs
|
||||
for _, each := range instance.Spec.DatabaseList {
|
||||
database, err := m.GetDB(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, each)
|
||||
database, err := m.GetDB(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Spec.Server, each)
|
||||
if err != nil {
|
||||
return sql.FailoverGroup{}, err
|
||||
}
|
||||
|
@ -172,12 +191,13 @@ func (m *AzureSqlFailoverGroupManager) TransformToSQLFailoverGroup(ctx context.C
|
|||
// CreateOrUpdateFailoverGroup creates a failover group
|
||||
func (m *AzureSqlFailoverGroupManager) CreateOrUpdateFailoverGroup(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroup string,
|
||||
server string,
|
||||
failoverGroupName string,
|
||||
failoverGroupProperties sql.FailoverGroup) (sql.FailoverGroupsCreateOrUpdateFuture, error) {
|
||||
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(m.Creds)
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.FailoverGroupsCreateOrUpdateFuture{}, err
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Azure/azure-service-operator/api"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/Azure/azure-service-operator/api"
|
||||
|
||||
azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1"
|
||||
"github.com/Azure/azure-service-operator/api/v1beta1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
|
@ -55,7 +56,7 @@ func (fg *AzureSqlFailoverGroupManager) Ensure(ctx context.Context, obj runtime.
|
|||
return true, nil
|
||||
}
|
||||
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(fg.Creds)
|
||||
failoverGroupsClient, err := azuresqlshared.GetGoFailoverGroupsClient(azuresqlshared.GetSubscriptionCredentials(fg.Creds, instance.Spec.SubscriptionID))
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "failed to create failovergroup client")
|
||||
}
|
||||
|
@ -122,7 +123,13 @@ func (fg *AzureSqlFailoverGroupManager) Ensure(ctx context.Context, obj runtime.
|
|||
// We need to reconcile as our state didn't match Azure
|
||||
instance.Status.SetProvisioning("")
|
||||
|
||||
future, err := fg.CreateOrUpdateFailoverGroup(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, failoverGroupName, failoverGroupProperties)
|
||||
future, err := fg.CreateOrUpdateFailoverGroup(
|
||||
ctx,
|
||||
instance.Spec.SubscriptionID,
|
||||
instance.Spec.ResourceGroup,
|
||||
instance.Spec.Server,
|
||||
failoverGroupName,
|
||||
failoverGroupProperties)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
allowedErrors := []string{
|
||||
|
@ -166,7 +173,7 @@ func (fg *AzureSqlFailoverGroupManager) Delete(ctx context.Context, obj runtime.
|
|||
// key for Secret to delete on successful provision
|
||||
secretKey := secrets.SecretKey{Name: instance.Name, Namespace: instance.Namespace, Kind: instance.TypeMeta.Kind}
|
||||
|
||||
_, err = fg.DeleteFailoverGroup(ctx, groupName, serverName, failoverGroupName)
|
||||
_, err = fg.DeleteFailoverGroup(ctx, instance.Spec.SubscriptionID, groupName, serverName, failoverGroupName)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
azerr := errhelp.NewAzureError(err)
|
||||
|
|
|
@ -6,8 +6,9 @@ package azuresqlfirewallrule
|
|||
import (
|
||||
"context"
|
||||
|
||||
sql "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
azuresqlshared "github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
|
@ -22,8 +23,8 @@ func NewAzureSqlFirewallRuleManager(creds config.Credentials) *AzureSqlFirewallR
|
|||
}
|
||||
|
||||
// GetServer returns a SQL server
|
||||
func (m *AzureSqlFirewallRuleManager) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.creds)
|
||||
func (m *AzureSqlFirewallRuleManager) GetServer(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Server{}, err
|
||||
}
|
||||
|
@ -36,8 +37,8 @@ func (m *AzureSqlFirewallRuleManager) GetServer(ctx context.Context, resourceGro
|
|||
}
|
||||
|
||||
// GetSQLFirewallRule returns a firewall rule
|
||||
func (m *AzureSqlFirewallRuleManager) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) {
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(m.creds)
|
||||
func (m *AzureSqlFirewallRuleManager) GetSQLFirewallRule(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) {
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.FirewallRule{}, err
|
||||
}
|
||||
|
@ -51,21 +52,21 @@ func (m *AzureSqlFirewallRuleManager) GetSQLFirewallRule(ctx context.Context, re
|
|||
}
|
||||
|
||||
// DeleteSQLFirewallRule deletes a firewall rule
|
||||
func (m *AzureSqlFirewallRuleManager) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) {
|
||||
func (m *AzureSqlFirewallRuleManager) DeleteSQLFirewallRule(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, ruleName string) (err error) {
|
||||
|
||||
// check to see if the server exists, if it doesn't then short-circuit
|
||||
server, err := m.GetServer(ctx, resourceGroupName, serverName)
|
||||
server, err := m.GetServer(ctx, subscriptionID, resourceGroupName, serverName)
|
||||
if err != nil || *server.State != "Ready" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check to see if the rule exists, if it doesn't then short-circuit
|
||||
_, err = m.GetSQLFirewallRule(ctx, resourceGroupName, serverName, ruleName)
|
||||
_, err = m.GetSQLFirewallRule(ctx, subscriptionID, resourceGroupName, serverName, ruleName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(m.creds)
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -83,15 +84,23 @@ func (m *AzureSqlFirewallRuleManager) DeleteSQLFirewallRule(ctx context.Context,
|
|||
// CreateOrUpdateSQLFirewallRule creates or updates a firewall rule
|
||||
// based on code from: https://github.com/Azure-Samples/azure-m-for-go-samples/blob/master/sql/sql.go#L111
|
||||
// to allow allow Azure services to connect example: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure#manage-firewall-rules-using-azure-cli
|
||||
func (m *AzureSqlFirewallRuleManager) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) {
|
||||
func (m *AzureSqlFirewallRuleManager) CreateOrUpdateSQLFirewallRule(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
ruleName string,
|
||||
startIP string,
|
||||
endIP string,
|
||||
) (result bool, err error) {
|
||||
|
||||
// check to see if the server exists, if it doesn't then short-circuit
|
||||
server, err := m.GetServer(ctx, resourceGroupName, serverName)
|
||||
server, err := m.GetServer(ctx, subscriptionID, resourceGroupName, serverName)
|
||||
if err != nil || *server.State != "Ready" {
|
||||
return false, err
|
||||
}
|
||||
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(m.creds)
|
||||
firewallClient, err := azuresqlshared.GetGoFirewallClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -7,13 +7,14 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1"
|
||||
"github.com/Azure/azure-service-operator/api/v1beta1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Ensure creates a sqlfirewallrule
|
||||
|
@ -23,13 +24,14 @@ func (fw *AzureSqlFirewallRuleManager) Ensure(ctx context.Context, obj runtime.O
|
|||
return false, err
|
||||
}
|
||||
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
server := instance.Spec.Server
|
||||
ruleName := instance.ObjectMeta.Name
|
||||
startIP := instance.Spec.StartIPAddress
|
||||
endIP := instance.Spec.EndIPAddress
|
||||
|
||||
fwr, err := fw.GetSQLFirewallRule(ctx, groupName, server, ruleName)
|
||||
fwr, err := fw.GetSQLFirewallRule(ctx, subscriptionID, groupName, server, ruleName)
|
||||
if err == nil {
|
||||
instance.Status.Provisioning = false
|
||||
instance.Status.Provisioned = true
|
||||
|
@ -48,7 +50,7 @@ func (fw *AzureSqlFirewallRuleManager) Ensure(ctx context.Context, obj runtime.O
|
|||
return false, nil
|
||||
}
|
||||
|
||||
_, err = fw.CreateOrUpdateSQLFirewallRule(ctx, groupName, server, ruleName, startIP, endIP)
|
||||
_, err = fw.CreateOrUpdateSQLFirewallRule(ctx, subscriptionID, groupName, server, ruleName, startIP, endIP)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
catch := []string{
|
||||
|
@ -74,11 +76,12 @@ func (fw *AzureSqlFirewallRuleManager) Delete(ctx context.Context, obj runtime.O
|
|||
return false, err
|
||||
}
|
||||
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
server := instance.Spec.Server
|
||||
ruleName := instance.ObjectMeta.Name
|
||||
|
||||
err = fw.DeleteSQLFirewallRule(ctx, groupName, server, ruleName)
|
||||
err = fw.DeleteSQLFirewallRule(ctx, subscriptionID, groupName, server, ruleName)
|
||||
if err != nil {
|
||||
catch := []string{
|
||||
errhelp.AsyncOpIncompleteError,
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
azuresql "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
mssql "github.com/denisenkom/go-mssqldb"
|
||||
uuid "github.com/gofrs/uuid"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
|
@ -37,8 +37,8 @@ func NewAzureSqlManagedUserManager(creds config.Credentials, secretClient secret
|
|||
}
|
||||
|
||||
// GetDB retrieves a database
|
||||
func (s *AzureSqlManagedUserManager) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (azuresql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(s.Creds)
|
||||
func (s *AzureSqlManagedUserManager) GetDB(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, databaseName string) (azuresql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(s.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return azuresql.Database{}, err
|
||||
}
|
||||
|
|
|
@ -8,13 +8,15 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/Azure/azure-service-operator/api/v1alpha1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
@ -42,7 +44,8 @@ func (s *AzureSqlManagedUserManager) Ensure(ctx context.Context, obj runtime.Obj
|
|||
secretClient = options.SecretClient
|
||||
}
|
||||
|
||||
_, err = s.GetDB(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
_, err = s.GetDB(ctx, subscriptionID, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
if err != nil {
|
||||
instance.Status.Message = errhelp.StripErrorIDs(err)
|
||||
|
||||
|
@ -155,7 +158,7 @@ func (s *AzureSqlManagedUserManager) Delete(ctx context.Context, obj runtime.Obj
|
|||
}
|
||||
|
||||
// short circuit connection if database doesn't exist
|
||||
_, err = s.GetDB(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
_, err = s.GetDB(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ func NewAzureSqlServerManager(creds config.Credentials, secretClient secrets.Sec
|
|||
}
|
||||
|
||||
// DeleteSQLServer deletes a SQL server
|
||||
func (m *AzureSqlServerManager) DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) {
|
||||
func (m *AzureSqlServerManager) DeleteSQLServer(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string) (result autorest.Response, err error) {
|
||||
result = autorest.Response{
|
||||
Response: &http.Response{
|
||||
StatusCode: 200,
|
||||
|
@ -43,12 +43,12 @@ func (m *AzureSqlServerManager) DeleteSQLServer(ctx context.Context, resourceGro
|
|||
}
|
||||
|
||||
// check to see if the server exists, if it doesn't then short-circuit
|
||||
_, err = m.GetServer(ctx, resourceGroupName, serverName)
|
||||
_, err = m.GetServer(ctx, subscriptionID, resourceGroupName, serverName)
|
||||
if err != nil {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.Creds)
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ func (m *AzureSqlServerManager) DeleteSQLServer(ctx context.Context, resourceGro
|
|||
}
|
||||
|
||||
// GetServer returns a SQL server
|
||||
func (m *AzureSqlServerManager) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.Creds)
|
||||
func (m *AzureSqlServerManager) GetServer(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string) (result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.Server{}, err
|
||||
}
|
||||
|
@ -80,8 +80,20 @@ func (m *AzureSqlServerManager) GetServer(ctx context.Context, resourceGroupName
|
|||
}
|
||||
|
||||
// CreateOrUpdateSQLServer creates a SQL server in Azure
|
||||
func (m *AzureSqlServerManager) CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, tags map[string]*string, properties azuresqlshared.SQLServerProperties, forceUpdate bool) (pollingURL string, result sql.Server, err error) {
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(m.Creds)
|
||||
func (m *AzureSqlServerManager) CreateOrUpdateSQLServer(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
location string,
|
||||
serverName string,
|
||||
tags map[string]*string,
|
||||
properties azuresqlshared.SQLServerProperties,
|
||||
forceUpdate bool,
|
||||
) (pollingURL string, result sql.Server, err error) {
|
||||
|
||||
creds := azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID)
|
||||
|
||||
serversClient, err := azuresqlshared.GetGoServersClient(creds)
|
||||
if err != nil {
|
||||
return "", sql.Server{}, err
|
||||
}
|
||||
|
@ -89,7 +101,7 @@ func (m *AzureSqlServerManager) CreateOrUpdateSQLServer(ctx context.Context, res
|
|||
serverProp := azuresqlshared.SQLServerPropertiesToServer(properties)
|
||||
|
||||
if forceUpdate == false {
|
||||
checkNameResult, _ := CheckNameAvailability(ctx, m.Creds, serverName)
|
||||
checkNameResult, _ := CheckNameAvailability(ctx, creds, serverName)
|
||||
if checkNameResult.Reason == sql.AlreadyExists {
|
||||
err = errors.New("AlreadyExists")
|
||||
return
|
||||
|
|
|
@ -66,7 +66,7 @@ func (s *AzureSqlServerManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
}
|
||||
if *checkNameResult.Available != true {
|
||||
instance.Status.Provisioning = false
|
||||
if _, err := s.GetServer(ctx, instance.Spec.ResourceGroup, instance.Name); err != nil {
|
||||
if _, err := s.GetServer(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Name); err != nil {
|
||||
instance.Status.Message = "SQL server already exists somewhere else"
|
||||
return true, nil
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func (s *AzureSqlServerManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
if instance.Status.Provisioning ||
|
||||
(!specHashWasEmpty && instance.Status.SpecHash == hash) {
|
||||
|
||||
serv, err := s.GetServer(ctx, instance.Spec.ResourceGroup, instance.Name)
|
||||
serv, err := s.GetServer(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Name)
|
||||
if err != nil {
|
||||
azerr := errhelp.NewAzureError(err)
|
||||
|
||||
|
@ -173,8 +173,17 @@ func (s *AzureSqlServerManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
|
||||
// create the sql server
|
||||
instance.Status.Provisioning = true
|
||||
if pollURL, _, err := s.CreateOrUpdateSQLServer(ctx, instance.Spec.ResourceGroup, instance.Spec.Location, instance.Name, tags, azureSQLServerProperties, false); err != nil {
|
||||
pollURL, _, err := s.CreateOrUpdateSQLServer(
|
||||
ctx,
|
||||
instance.Spec.SubscriptionID,
|
||||
instance.Spec.ResourceGroup,
|
||||
instance.Spec.Location,
|
||||
instance.Name,
|
||||
tags,
|
||||
azureSQLServerProperties,
|
||||
false)
|
||||
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
|
||||
// check for our known errors
|
||||
|
@ -191,7 +200,7 @@ func (s *AzureSqlServerManager) Ensure(ctx context.Context, obj runtime.Object,
|
|||
// SQL Server names are globally unique so if a server with this name exists we
|
||||
// need to see if it meets our criteria (ie. same rg/sub)
|
||||
// see if server exists in correct rg
|
||||
if serv, err := s.GetServer(ctx, instance.Spec.ResourceGroup, instance.Name); err == nil {
|
||||
if serv, err := s.GetServer(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Name); err == nil {
|
||||
// mismatched location
|
||||
if *serv.Location != instance.Spec.Location {
|
||||
instance.Status.Provisioned = false
|
||||
|
@ -263,6 +272,7 @@ func (s *AzureSqlServerManager) Delete(ctx context.Context, obj runtime.Object,
|
|||
return false, err
|
||||
}
|
||||
|
||||
subscriptionID := instance.Spec.SubscriptionID
|
||||
name := instance.ObjectMeta.Name
|
||||
groupName := instance.Spec.ResourceGroup
|
||||
secretKey := secrets.SecretKey{Name: instance.Name, Namespace: instance.Namespace, Kind: instance.TypeMeta.Kind}
|
||||
|
@ -273,7 +283,7 @@ func (s *AzureSqlServerManager) Delete(ctx context.Context, obj runtime.Object,
|
|||
return false, nil
|
||||
}
|
||||
|
||||
_, err = s.DeleteSQLServer(ctx, groupName, name)
|
||||
_, err = s.DeleteSQLServer(ctx, subscriptionID, groupName, name)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
azerr := errhelp.NewAzureError(err)
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
package azuresqlshared
|
||||
|
||||
import (
|
||||
network "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network"
|
||||
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network"
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
sql3 "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/iam"
|
||||
)
|
||||
|
@ -72,8 +73,8 @@ func GetGoVNetRulesClient(creds config.Credentials) (sql.VirtualNetworkRulesClie
|
|||
}
|
||||
|
||||
// GetNetworkSubnetClient retrieves a Subnetclient
|
||||
func GetGoNetworkSubnetClient(creds config.Credentials, subscription string) (network.SubnetsClient, error) {
|
||||
subnetsClient := network.NewSubnetsClientWithBaseURI(config.BaseURI(), subscription)
|
||||
func GetGoNetworkSubnetClient(creds config.Credentials) (network.SubnetsClient, error) {
|
||||
subnetsClient := network.NewSubnetsClientWithBaseURI(config.BaseURI(), creds.SubscriptionID())
|
||||
a, err := iam.GetResourceManagementAuthorizer(creds)
|
||||
if err != nil {
|
||||
return network.SubnetsClient{}, err
|
||||
|
@ -106,3 +107,11 @@ func GetBackupShortTermRetentionPoliciesClient(creds config.Credentials) (sql3.B
|
|||
backupClient.AddToUserAgent(config.UserAgent())
|
||||
return backupClient, nil
|
||||
}
|
||||
|
||||
func GetSubscriptionCredentials(creds config.Credentials, subscriptionID string) config.Credentials {
|
||||
if subscriptionID == "" {
|
||||
return creds
|
||||
}
|
||||
|
||||
return creds.WithSubscriptionID(subscriptionID)
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ func NewAzureSqlUserManager(creds config.Credentials, secretClient secrets.Secre
|
|||
}
|
||||
|
||||
// GetDB retrieves a database
|
||||
func (m *AzureSqlUserManager) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (azuresql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(m.Creds)
|
||||
func (m *AzureSqlUserManager) GetDB(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, databaseName string) (azuresql.Database, error) {
|
||||
dbClient, err := azuresqlshared.GetGoDbClient(azuresqlshared.GetSubscriptionCredentials(m.Creds, subscriptionID))
|
||||
if err != nil {
|
||||
return azuresql.Database{}, err
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func (s *AzureSqlUserManager) Ensure(ctx context.Context, obj runtime.Object, op
|
|||
userSecretClient = s.SecretClient
|
||||
}
|
||||
|
||||
_, err = s.GetDB(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
_, err = s.GetDB(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
if err != nil {
|
||||
instance.Status.Message = errhelp.StripErrorIDs(err)
|
||||
instance.Status.Provisioning = false
|
||||
|
@ -329,7 +329,7 @@ func (s *AzureSqlUserManager) Delete(ctx context.Context, obj runtime.Object, op
|
|||
}
|
||||
|
||||
// short circuit connection if database doesn't exist
|
||||
_, err = s.GetDB(ctx, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
_, err = s.GetDB(ctx, instance.Spec.SubscriptionID, instance.Spec.ResourceGroup, instance.Spec.Server, instance.Spec.DbName)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@ package azuresqlvnetrule
|
|||
import (
|
||||
"context"
|
||||
|
||||
sql "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
azuresqlshared "github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/azuresql/azuresqlshared"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/config"
|
||||
)
|
||||
|
||||
|
@ -20,13 +21,20 @@ func NewAzureSqlVNetRuleManager(creds config.Credentials) *AzureSqlVNetRuleManag
|
|||
}
|
||||
|
||||
// GetSQLVNetRule returns a VNet rule
|
||||
func (m *AzureSqlVNetRuleManager) GetSQLVNetRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.VirtualNetworkRule, err error) {
|
||||
VNetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(m.creds)
|
||||
func (m *AzureSqlVNetRuleManager) GetSQLVNetRule(
|
||||
ctx context.Context,
|
||||
subscriptionID string,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
ruleName string,
|
||||
) (result sql.VirtualNetworkRule, err error) {
|
||||
|
||||
vnetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return sql.VirtualNetworkRule{}, err
|
||||
}
|
||||
|
||||
return VNetRulesClient.Get(
|
||||
return vnetRulesClient.Get(
|
||||
ctx,
|
||||
resourceGroupName,
|
||||
serverName,
|
||||
|
@ -35,20 +43,20 @@ func (m *AzureSqlVNetRuleManager) GetSQLVNetRule(ctx context.Context, resourceGr
|
|||
}
|
||||
|
||||
// DeleteSQLVNetRule deletes a VNet rule
|
||||
func (m *AzureSqlVNetRuleManager) DeleteSQLVNetRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) {
|
||||
func (m *AzureSqlVNetRuleManager) DeleteSQLVNetRule(ctx context.Context, subscriptionID string, resourceGroupName string, serverName string, ruleName string) (err error) {
|
||||
|
||||
// check to see if the rule exists, if it doesn't then short-circuit
|
||||
_, err = m.GetSQLVNetRule(ctx, resourceGroupName, serverName, ruleName)
|
||||
_, err = m.GetSQLVNetRule(ctx, subscriptionID, resourceGroupName, serverName, ruleName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
VNetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(m.creds)
|
||||
vnetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(azuresqlshared.GetSubscriptionCredentials(m.creds, subscriptionID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = VNetRulesClient.Delete(
|
||||
_, err = vnetRulesClient.Delete(
|
||||
ctx,
|
||||
resourceGroupName,
|
||||
serverName,
|
||||
|
@ -60,9 +68,20 @@ func (m *AzureSqlVNetRuleManager) DeleteSQLVNetRule(ctx context.Context, resourc
|
|||
|
||||
// CreateOrUpdateSQLVNetRule creates or updates a VNet rule
|
||||
// based on code from: https://godoc.org/github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql#VirtualNetworkRulesClient.CreateOrUpdate
|
||||
func (m *AzureSqlVNetRuleManager) CreateOrUpdateSQLVNetRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, VNetRG string, VNetName string, SubnetName string, subscription string, IgnoreServiceEndpoint bool) (vnr sql.VirtualNetworkRule, err error) {
|
||||
func (m *AzureSqlVNetRuleManager) CreateOrUpdateSQLVNetRule(
|
||||
ctx context.Context,
|
||||
resourceGroupName string,
|
||||
serverName string,
|
||||
ruleName string,
|
||||
VNetRG string,
|
||||
VNetName string,
|
||||
SubnetName string,
|
||||
subscription string,
|
||||
IgnoreServiceEndpoint bool,
|
||||
) (vnr sql.VirtualNetworkRule, err error) {
|
||||
|
||||
VNetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(m.creds)
|
||||
creds := azuresqlshared.GetSubscriptionCredentials(m.creds, subscription)
|
||||
VNetRulesClient, err := azuresqlshared.GetGoVNetRulesClient(creds)
|
||||
if err != nil {
|
||||
return sql.VirtualNetworkRule{}, err
|
||||
}
|
||||
|
@ -71,7 +90,7 @@ func (m *AzureSqlVNetRuleManager) CreateOrUpdateSQLVNetRule(ctx context.Context,
|
|||
if subscription == "" {
|
||||
subscription = m.creds.SubscriptionID()
|
||||
}
|
||||
SubnetClient, err := azuresqlshared.GetGoNetworkSubnetClient(m.creds, subscription)
|
||||
SubnetClient, err := azuresqlshared.GetGoNetworkSubnetClient(creds)
|
||||
if err != nil {
|
||||
return sql.VirtualNetworkRule{}, err
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1"
|
||||
"github.com/Azure/azure-service-operator/pkg/errhelp"
|
||||
"github.com/Azure/azure-service-operator/pkg/helpers"
|
||||
"github.com/Azure/azure-service-operator/pkg/resourcemanager"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Ensure creates a sqlvnetrule
|
||||
|
@ -31,9 +32,10 @@ func (vr *AzureSqlVNetRuleManager) Ensure(ctx context.Context, obj runtime.Objec
|
|||
virtualnetworkname := instance.Spec.VNetName
|
||||
subnetName := instance.Spec.SubnetName
|
||||
virtualNetworkSubscription := instance.Spec.VNetSubscriptionID
|
||||
serverSubscriptionID := instance.Spec.ServerSubscriptionID
|
||||
ignoreendpoint := instance.Spec.IgnoreMissingServiceEndpoint
|
||||
|
||||
vnetrule, err := vr.GetSQLVNetRule(ctx, groupName, server, ruleName)
|
||||
vnetrule, err := vr.GetSQLVNetRule(ctx, serverSubscriptionID, groupName, server, ruleName)
|
||||
if err == nil {
|
||||
if vnetrule.VirtualNetworkRuleProperties != nil && vnetrule.VirtualNetworkRuleProperties.State == sql.VirtualNetworkRuleStateReady {
|
||||
instance.Status.Provisioning = false
|
||||
|
@ -100,8 +102,9 @@ func (vr *AzureSqlVNetRuleManager) Delete(ctx context.Context, obj runtime.Objec
|
|||
groupName := instance.Spec.ResourceGroup
|
||||
server := instance.Spec.Server
|
||||
ruleName := instance.ObjectMeta.Name
|
||||
subscriptionID := instance.Spec.ServerSubscriptionID
|
||||
|
||||
err = vr.DeleteSQLVNetRule(ctx, groupName, server, ruleName)
|
||||
err = vr.DeleteSQLVNetRule(ctx, subscriptionID, groupName, server, ruleName)
|
||||
if err != nil {
|
||||
instance.Status.Message = err.Error()
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ type Credentials interface {
|
|||
SubscriptionID() string
|
||||
UseManagedIdentity() bool
|
||||
OperatorKeyvault() string
|
||||
|
||||
WithSubscriptionID(subscriptionID string) Credentials
|
||||
}
|
||||
|
||||
type credentials struct {
|
||||
|
@ -56,3 +58,11 @@ func (c credentials) UseManagedIdentity() bool {
|
|||
func (c credentials) OperatorKeyvault() string {
|
||||
return c.operatorKeyvault
|
||||
}
|
||||
|
||||
// WithSubscriptionID returns the credentials object with a different subscription ID.
|
||||
// The original credentials object is not modified
|
||||
func (c credentials) WithSubscriptionID(subscriptionID string) Credentials {
|
||||
c.subscriptionID = subscriptionID
|
||||
|
||||
return c
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (m *azureConsumerGroupManager) DeleteConsumerGroup(ctx context.Context, res
|
|||
)
|
||||
}
|
||||
|
||||
//GetConsumerGroup gets consumer group description for the specified Consumer Group.
|
||||
// GetConsumerGroup gets consumer group description for the specified Consumer Group.
|
||||
func (m *azureConsumerGroupManager) GetConsumerGroup(ctx context.Context, resourceGroupName string, namespaceName string, eventHubName string, consumerGroupName string) (eventhub.ConsumerGroup, error) {
|
||||
consumerGroupClient, err := getConsumerGroupsClient(m.creds)
|
||||
if err != nil {
|
||||
|
|
|
@ -12,17 +12,17 @@ import (
|
|||
"github.com/Azure/azure-service-operator/pkg/resourcemanager/iam"
|
||||
)
|
||||
|
||||
//MySQLDatabaseClient struct
|
||||
// MySQLDatabaseClient struct
|
||||
type MySQLDatabaseClient struct {
|
||||
creds config.Credentials
|
||||
}
|
||||
|
||||
//NewMySQLDatabaseClient create a new MySQLDatabaseClient
|
||||
// NewMySQLDatabaseClient create a new MySQLDatabaseClient
|
||||
func NewMySQLDatabaseClient(creds config.Credentials) *MySQLDatabaseClient {
|
||||
return &MySQLDatabaseClient{creds: creds}
|
||||
}
|
||||
|
||||
//GetMySQLDatabasesClient return the mysqldatabaseclient
|
||||
// GetMySQLDatabasesClient return the mysqldatabaseclient
|
||||
func GetMySQLDatabasesClient(creds config.Credentials) mysql.DatabasesClient {
|
||||
databasesClient := mysql.NewDatabasesClientWithBaseURI(config.BaseURI(), creds.SubscriptionID())
|
||||
a, _ := iam.GetResourceManagementAuthorizer(creds)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/Azure/azure-service-operator/pkg/secrets"
|
||||
)
|
||||
|
||||
//MySQLUser interface provides the functions of mySQLUser
|
||||
// MySQLUser interface provides the functions of mySQLUser
|
||||
type MySQLUser interface {
|
||||
GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (mysql.Database, error)
|
||||
ConnectToMySqlDb(ctx context.Context, drivername string, server string, dbname string, port int, username string, password string) (*sql.DB, error)
|
||||
|
|
|
@ -20,7 +20,7 @@ func NewPSQLDatabaseClient(creds config.Credentials) *PSQLDatabaseClient {
|
|||
return &PSQLDatabaseClient{creds: creds}
|
||||
}
|
||||
|
||||
//GetPSQLDatabasesClient retrieves the psqldabase
|
||||
// GetPSQLDatabasesClient retrieves the psqldabase
|
||||
func GetPSQLDatabasesClient(creds config.Credentials) (psql.DatabasesClient, error) {
|
||||
databasesClient := psql.NewDatabasesClientWithBaseURI(config.BaseURI(), creds.SubscriptionID())
|
||||
a, err := iam.GetResourceManagementAuthorizer(creds)
|
||||
|
|
|
@ -33,14 +33,14 @@ const PSecretUsernameKey = "username"
|
|||
// PSecretPasswordKey is the password key in secret
|
||||
const PSecretPasswordKey = "password"
|
||||
|
||||
//PostgreSqlUserManager for psqluser manager
|
||||
// PostgreSqlUserManager for psqluser manager
|
||||
type PostgreSqlUserManager struct {
|
||||
Creds config.Credentials
|
||||
SecretClient secrets.SecretClient
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
//NewPostgreSqlUserManager creates a new PostgreSqlUserManager
|
||||
// NewPostgreSqlUserManager creates a new PostgreSqlUserManager
|
||||
func NewPostgreSqlUserManager(creds config.Credentials, secretClient secrets.SecretClient, scheme *runtime.Scheme) *PostgreSqlUserManager {
|
||||
return &PostgreSqlUserManager{
|
||||
Creds: creds,
|
||||
|
|
|
@ -74,7 +74,7 @@ func (c *PostgreSQLVNetRuleClient) DeletePostgreSQLVNetRule(ctx context.Context,
|
|||
return err
|
||||
}
|
||||
|
||||
// creates or updates a VNet rule
|
||||
// creates or updates a VNet rule
|
||||
func (c *PostgreSQLVNetRuleClient) CreateOrUpdatePostgreSQLVNetRule(
|
||||
ctx context.Context,
|
||||
resourceGroupName string,
|
||||
|
|
|
@ -36,7 +36,7 @@ func (m *AzureRedisManager) GetRedisCacheClient() (redis.Client, error) {
|
|||
return redisClient, nil
|
||||
}
|
||||
|
||||
//ListKeys lists the keys for redis cache
|
||||
// ListKeys lists the keys for redis cache
|
||||
func (m *AzureRedisManager) ListKeys(ctx context.Context, resourceGroupName string, redisCacheName string) (result redis.AccessKeys, err error) {
|
||||
redisClient, err := m.GetRedisCacheClient()
|
||||
if err != nil {
|
||||
|
|
|
@ -17,7 +17,7 @@ type AzureSubnetManager struct {
|
|||
creds config.Credentials
|
||||
}
|
||||
|
||||
//NewAzureSubnetManager returns a new client for subnets
|
||||
// NewAzureSubnetManager returns a new client for subnets
|
||||
func NewAzureSubnetManager(creds config.Credentials) *AzureSubnetManager {
|
||||
return &AzureSubnetManager{creds: creds}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func (m *AzureSubnetManager) Get(ctx context.Context, resourceGroup, vnet, subne
|
|||
return client.Get(ctx, resourceGroup, vnet, subnet, "")
|
||||
}
|
||||
|
||||
//SubnetID models the parts of a subnet resource id
|
||||
// SubnetID models the parts of a subnet resource id
|
||||
type SubnetID struct {
|
||||
Name string
|
||||
VNet string
|
||||
|
@ -54,7 +54,7 @@ type SubnetID struct {
|
|||
Subscription string
|
||||
}
|
||||
|
||||
//ParseSubnetID takes a resource id for a subnet and parses it into its parts
|
||||
// ParseSubnetID takes a resource id for a subnet and parses it into its parts
|
||||
func ParseSubnetID(sid string) SubnetID {
|
||||
parts := strings.Split(sid, "/")
|
||||
subid := SubnetID{}
|
||||
|
|
|
@ -54,7 +54,7 @@ func CreateKeyVaultSoftDeleteEnabled(ctx context.Context, creds config.Credentia
|
|||
return future.WaitForCompletionRef(ctx, vaultsClient.Client)
|
||||
}
|
||||
|
||||
//CreateVaultWithAccessPolicies creates a new key vault and provides access policies to the specified user - used in test
|
||||
// CreateVaultWithAccessPolicies creates a new key vault and provides access policies to the specified user - used in test
|
||||
func CreateVaultWithAccessPolicies(ctx context.Context, creds config.Credentials, groupName string, vaultName string, location string, objectID *string) error {
|
||||
vaultsClient, err := kvhelper.GetKeyVaultClient(creds)
|
||||
if err != nil {
|
||||
|
|
Загрузка…
Ссылка в новой задаче