-
Notifications
You must be signed in to change notification settings - Fork 860
refactor: refactor the domain / cli commands for active-active's cluster-attr #7299
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ import ( | |
"errors" | ||
"fmt" | ||
"os" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
@@ -112,16 +113,6 @@ func (d *domainCLIImpl) RegisterDomain(c *cli.Context) error { | |
return commoncli.Problem(fmt.Sprintf("Option %s format is invalid.", FlagIsGlobalDomain), err) | ||
} | ||
} | ||
isActiveActiveDomain := false | ||
if c.IsSet(FlagIsActiveActiveDomain) { | ||
isActiveActiveDomain, err = strconv.ParseBool(c.String(FlagIsActiveActiveDomain)) | ||
if err != nil { | ||
return commoncli.Problem(fmt.Sprintf("Option %s format is invalid.", FlagIsActiveActiveDomain), err) | ||
} | ||
|
||
// Also set isGlobalDomain to true if it is active-active domain | ||
isGlobalDomain = isActiveActiveDomain | ||
} | ||
|
||
var domainData *flag.StringMap | ||
if c.IsSet(FlagDomainData) { | ||
|
@@ -136,17 +127,9 @@ func (d *domainCLIImpl) RegisterDomain(c *cli.Context) error { | |
|
||
activeClusterName := "" | ||
if c.IsSet(FlagActiveClusterName) { | ||
if isActiveActiveDomain { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i.. am not actually sure what the behaviour here should be |
||
return commoncli.Problem("Option --active_cluster is not supported for active-active domain. Use --active_clusters_by_region instead.", nil) | ||
} | ||
activeClusterName = c.String(FlagActiveClusterName) | ||
} | ||
|
||
activeClustersByRegion, err := parseActiveClustersByRegion(c, isActiveActiveDomain) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var clusters []*types.ClusterReplicationConfiguration | ||
if c.IsSet(FlagClusters) { | ||
for _, clusterStr := range c.StringSlice(FlagClusters) { | ||
|
@@ -165,6 +148,15 @@ func (d *domainCLIImpl) RegisterDomain(c *cli.Context) error { | |
return fmt.Errorf("failed to parse %s flag: %w", FlagVisibilityArchivalStatus, err) | ||
} | ||
|
||
var activeClusters *types.ActiveClusters | ||
if c.IsSet(FlagActiveClusters) { | ||
ac, err := parseActiveClustersByClusterAttribute(c.String(FlagActiveClusters)) | ||
if err != nil { | ||
return err | ||
} | ||
activeClusters = &ac | ||
} | ||
|
||
request := &types.RegisterDomainRequest{ | ||
Name: domainName, | ||
Description: description, | ||
|
@@ -173,7 +165,7 @@ func (d *domainCLIImpl) RegisterDomain(c *cli.Context) error { | |
WorkflowExecutionRetentionPeriodInDays: int32(retentionDays), | ||
Clusters: clusters, | ||
ActiveClusterName: activeClusterName, | ||
ActiveClustersByRegion: activeClustersByRegion, | ||
ActiveClusters: activeClusters, | ||
SecurityToken: securityToken, | ||
HistoryArchivalStatus: has, | ||
HistoryArchivalURI: c.String(FlagHistoryArchivalURI), | ||
|
@@ -225,23 +217,16 @@ func (d *domainCLIImpl) UpdateDomain(c *cli.Context) error { | |
ActiveClusterName: common.StringPtr(activeCluster), | ||
FailoverTimeoutInSeconds: failoverTimeout, | ||
} | ||
} else if c.IsSet(FlagActiveClustersByRegion) { // active-active domain failover | ||
activeClustersByRegion, err := parseActiveClustersByRegion(c, true) | ||
} else if c.IsSet(FlagActiveClusters) { // active-active domain failover | ||
activeClusters, err := parseActiveClustersByClusterAttribute(c.String(FlagActiveClusters)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
acbr := make(map[string]types.ActiveClusterInfo) | ||
for region, cluster := range activeClustersByRegion { | ||
acbr[region] = types.ActiveClusterInfo{ | ||
ActiveClusterName: cluster, | ||
} | ||
} | ||
|
||
updateRequest = &types.UpdateDomainRequest{ | ||
Name: domainName, | ||
ActiveClusters: &types.ActiveClusters{ | ||
ActiveClustersByRegion: acbr, | ||
AttributeScopes: activeClusters.AttributeScopes, | ||
}, | ||
} | ||
} else { | ||
|
@@ -634,26 +619,27 @@ type ActiveClusterInfoRow struct { | |
} | ||
|
||
type DomainRow struct { | ||
Name string `header:"Name"` | ||
UUID string `header:"UUID"` | ||
Description string | ||
OwnerEmail string | ||
DomainData map[string]string `header:"Domain Data"` | ||
Status types.DomainStatus `header:"Status"` | ||
IsGlobal bool `header:"Is Global Domain"` | ||
ActiveCluster string `header:"Active Cluster"` | ||
Clusters []string `header:"Clusters"` | ||
RetentionDays int32 `header:"Retention Days"` | ||
EmitMetrics bool | ||
HistoryArchivalStatus types.ArchivalStatus `header:"History Archival Status"` | ||
HistoryArchivalURI string `header:"History Archival URI"` | ||
VisibilityArchivalStatus types.ArchivalStatus `header:"Visibility Archival Status"` | ||
VisibilityArchivalURI string `header:"Visibility Archival URI"` | ||
BadBinaries []BadBinaryRow | ||
FailoverInfo *FailoverInfoRow | ||
LongRunningWorkFlowNum *int | ||
IsActiveActiveDomain bool | ||
ActiveClustersByRegion []ActiveClusterInfoRow | ||
Name string `header:"Name"` | ||
UUID string `header:"UUID"` | ||
Description string | ||
OwnerEmail string | ||
DomainData map[string]string `header:"Domain Data"` | ||
Status types.DomainStatus `header:"Status"` | ||
IsGlobal bool `header:"Is Global Domain"` | ||
ActiveCluster string `header:"Active Cluster"` | ||
Clusters []string `header:"Clusters"` | ||
RetentionDays int32 `header:"Retention Days"` | ||
EmitMetrics bool | ||
HistoryArchivalStatus types.ArchivalStatus `header:"History Archival Status"` | ||
HistoryArchivalURI string `header:"History Archival URI"` | ||
VisibilityArchivalStatus types.ArchivalStatus `header:"Visibility Archival Status"` | ||
VisibilityArchivalURI string `header:"Visibility Archival URI"` | ||
BadBinaries []BadBinaryRow | ||
FailoverInfo *FailoverInfoRow | ||
LongRunningWorkFlowNum *int | ||
IsActiveActiveDomain bool | ||
ActiveClustersByRegion []ActiveClusterInfoRow // todo (david.porter) remove this as it's not in use | ||
ActiveClustersByClusterAttribute []ActiveClusterInfoRow | ||
} | ||
|
||
type DomainMigrationRow struct { | ||
|
@@ -697,7 +683,7 @@ func newDomainRow(domain *types.DescribeDomainResponse) DomainRow { | |
VisibilityArchivalURI: domain.Configuration.GetVisibilityArchivalURI(), | ||
BadBinaries: newBadBinaryRows(domain.Configuration.BadBinaries), | ||
FailoverInfo: newFailoverInfoRow(domain.FailoverInfo), | ||
IsActiveActiveDomain: domain.ReplicationConfiguration.GetActiveClusters() != nil, | ||
IsActiveActiveDomain: domain.ReplicationConfiguration.IsActiveActiveDomain(), | ||
ActiveClustersByRegion: newActiveClustersByRegion(domain.ReplicationConfiguration.GetActiveClusters()), | ||
} | ||
} | ||
|
@@ -925,27 +911,42 @@ func clustersToStrings(clusters []*types.ClusterReplicationConfiguration) []stri | |
return res | ||
} | ||
|
||
func parseActiveClustersByRegion(c *cli.Context, isActiveActiveDomain bool) (map[string]string, error) { | ||
var activeClustersByRegion map[string]string | ||
if c.IsSet(FlagActiveClustersByRegion) { | ||
if !isActiveActiveDomain { | ||
return nil, commoncli.Problem("Option --active_clusters_by_region is only supported for active-active domain. Use --active_cluster instead.", nil) | ||
func parseActiveClustersByClusterAttribute(clusters string) (types.ActiveClusters, error) { | ||
split := regexp.MustCompile(`(?P<attribute>[a-zA-Z0-9_]+).(?P<scope>[a-zA-Z0-9_]+):(?P<name>[a-zA-Z0-9_]+)`) | ||
matches := split.FindAllStringSubmatch(clusters, -1) | ||
if len(matches) == 0 { | ||
return types.ActiveClusters{}, fmt.Errorf("option %s format is invalid. Expected format is 'region.dca:dev2_dca,region.phx:dev2_phx'", FlagActiveClusters) | ||
} | ||
|
||
out := types.ActiveClusters{ | ||
AttributeScopes: map[string]types.ClusterAttributeScope{}, | ||
} | ||
|
||
for _, match := range matches { | ||
if len(match) != 4 { | ||
return types.ActiveClusters{}, fmt.Errorf("option %s format is invalid. Expected format is 'region.dca:dev2_dca,region.phx:dev2_phx'", FlagActiveClusters) | ||
} | ||
attribute := match[1] | ||
scope := match[2] | ||
name := match[3] | ||
|
||
activeClustersByRegion = make(map[string]string) | ||
for _, regionCluster := range c.StringSlice(FlagActiveClustersByRegion) { | ||
splitted := strings.Split(regionCluster, ":") | ||
if len(splitted) != 2 { | ||
return nil, commoncli.Problem(fmt.Sprintf("Option --%s format is invalid. Expected format is 'region1:cluster1,region2:cluster2'", FlagActiveClustersByRegion), nil) | ||
existing, ok := out.AttributeScopes[attribute] | ||
if !ok { | ||
out.AttributeScopes[attribute] = types.ClusterAttributeScope{ | ||
ClusterAttributes: map[string]types.ActiveClusterInfo{ | ||
scope: {ActiveClusterName: name}, | ||
}, | ||
} | ||
region, cluster := strings.TrimSpace(splitted[0]), strings.TrimSpace(splitted[1]) | ||
activeClustersByRegion[region] = cluster | ||
} else { | ||
if _, ok := existing.ClusterAttributes[scope]; ok { | ||
return types.ActiveClusters{}, fmt.Errorf("option active_clusters format is invalid. the key %q was duplicated. This can only map to a single active cluster", scope) | ||
} | ||
existing.ClusterAttributes[scope] = types.ActiveClusterInfo{ActiveClusterName: name} | ||
out.AttributeScopes[attribute] = existing | ||
} | ||
} | ||
|
||
if isActiveActiveDomain && len(activeClustersByRegion) == 0 { | ||
return nil, commoncli.Problem("Option --active_clusters_by_region is required for active-active domain.", nil) | ||
out.AttributeScopes[attribute].ClusterAttributes[scope] = types.ActiveClusterInfo{ActiveClusterName: name} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we might check duplication and return an error here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I think my impl is a bit loose. let me add a bit more validation |
||
} | ||
|
||
return activeClustersByRegion, nil | ||
return out, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not new, it's just shuffled from below due to my removing and then re-adding it. Happy to put it back in it's previous spot if necessary