forked from hashicorp/terraform-provider-azurerm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.go
111 lines (95 loc) · 5.09 KB
/
database.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package helper
import (
"context"
"fmt"
"log"
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v5.0/sql"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-06-01/resources"
"github.com/kevinklinger/terraform-provider-azurerm/v2/internal/location"
"github.com/kevinklinger/terraform-provider-azurerm/v2/internal/services/mssql/parse"
"github.com/kevinklinger/terraform-provider-azurerm/v2/utils"
)
// FindDatabaseReplicationPartners looks for partner databases having one of the specified replication roles, by
// reading any replication links then attempting to discover and match the corresponding server/database resources for
// the other end of the link.
func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *sql.DatabasesClient, replicationLinksClient *sql.ReplicationLinksClient, resourcesClient *resources.Client, id parse.DatabaseId, rolesToFind []sql.ReplicationRole) ([]sql.Database, error) {
var partnerDatabases []sql.Database
matchesRole := func(role sql.ReplicationRole) bool {
for _, r := range rolesToFind {
if r == role {
return true
}
}
return false
}
for linksIterator, err := replicationLinksClient.ListByDatabaseComplete(ctx, id.ResourceGroup, id.ServerName, id.Name); linksIterator.NotDone(); err = linksIterator.NextWithContext(ctx) {
if err != nil {
return nil, fmt.Errorf("reading Replication Links for %s: %+v", id, err)
}
if linksIterator.Response().IsEmpty() {
return nil, fmt.Errorf("reading Replication Links for %s: response was empty", id)
}
linkProps := linksIterator.Value().ReplicationLinkProperties
if linkProps == nil {
log.Printf("[INFO] Replication Link Properties was nil for %s", id)
continue
}
if linkProps.PartnerLocation == nil || linkProps.PartnerServer == nil || linkProps.PartnerDatabase == nil {
log.Printf("[INFO] Replication Link Properties was invalid for %s", id)
continue
}
log.Printf("[INFO] Replication Link found for %s", id)
// Look for candidate partner SQL servers
filter := fmt.Sprintf("(resourceType eq 'Microsoft.Sql/servers') and ((name eq '%s'))", *linkProps.PartnerServer)
var resourceList []resources.GenericResourceExpanded
for resourcesIterator, err := resourcesClient.ListComplete(ctx, filter, "", nil); resourcesIterator.NotDone(); err = resourcesIterator.NextWithContext(ctx) {
if err != nil {
return nil, fmt.Errorf("retrieving Partner SQL Servers with filter %q for %s: %+v", filter, id, err)
}
resourceList = append(resourceList, resourcesIterator.Value())
}
for _, server := range resourceList {
if server.ID == nil {
log.Printf("[INFO] Partner SQL Server ID was nil for %s", id)
continue
}
partnerServerId, err := parse.ServerID(*server.ID)
if err != nil {
return nil, fmt.Errorf("parsing Partner SQL Server ID %q: %+v", *server.ID, err)
}
// Check if like-named server has a database named like the partner database, also with a replication link
for linksPossiblePartnerIterator, err := replicationLinksClient.ListByDatabaseComplete(ctx, partnerServerId.ResourceGroup, partnerServerId.Name, *linkProps.PartnerDatabase); linksPossiblePartnerIterator.NotDone(); err = linksPossiblePartnerIterator.NextWithContext(ctx) {
if err != nil {
if utils.ResponseWasNotFound(linksPossiblePartnerIterator.Response().Response) {
log.Printf("[INFO] no replication link found for Database %q (%s)", *linkProps.PartnerDatabase, partnerServerId)
continue
}
return nil, fmt.Errorf("reading Replication Links for Database %s (%s): %+v", *linkProps.PartnerDatabase, partnerServerId, err)
}
linkPossiblePartner := linksPossiblePartnerIterator.Value()
if linkPossiblePartner.ReplicationLinkProperties == nil {
log.Printf("[INFO] Replication Link Properties was nil for Database %s (%s)", *linkProps.PartnerDatabase, partnerServerId)
continue
}
linkPropsPossiblePartner := *linkPossiblePartner.ReplicationLinkProperties
// If the database has a replication link for the specified role, we'll consider it a partner of this database if the location is the same as expected partner
if matchesRole(linkPropsPossiblePartner.Role) {
partnerDatabaseId := parse.NewDatabaseID(partnerServerId.SubscriptionId, partnerServerId.ResourceGroup, partnerServerId.Name, *linkProps.PartnerDatabase)
partnerDatabase, err := databasesClient.Get(ctx, partnerDatabaseId.ResourceGroup, partnerDatabaseId.ServerName, partnerDatabaseId.Name)
if err != nil {
return nil, fmt.Errorf("retrieving Partner %s: %+v", partnerDatabaseId, err)
}
if location.NormalizeNilable(partnerDatabase.Location) != location.Normalize(*linkProps.PartnerLocation) {
log.Printf("[INFO] Mismatch of possible Partner Database based on location (%s vs %s) for %s", location.NormalizeNilable(partnerDatabase.Location), location.Normalize(*linkProps.PartnerLocation), id)
continue
}
if partnerDatabase.ID != nil {
log.Printf("[INFO] Found Partner %s", partnerDatabaseId)
partnerDatabases = append(partnerDatabases, partnerDatabase)
}
}
}
}
}
return partnerDatabases, nil
}