first commit

This commit is contained in:
2024-10-28 23:04:48 +01:00
commit 1ee55157f1
911 changed files with 325331 additions and 0 deletions

215
internal/ha/ha.go Normal file
View File

@@ -0,0 +1,215 @@
/*
© Copyright IBM Corporation 2020, 2024
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package ha contains code for high availability
package ha
import (
"fmt"
"os"
"github.com/ibm-messaging/mq-container/internal/fips"
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
"github.com/ibm-messaging/mq-container/internal/tls"
"github.com/ibm-messaging/mq-container/pkg/logger"
)
// ConfigureNativeHA configures native high availability
func ConfigureNativeHA(log *logger.Logger) error {
if os.Getenv("MQ_NATIVE_HA") != "true" {
return nil
}
fipsAvailable := fips.IsFIPSEnabled()
haCertLabel, haGroupCertLabel, _, _, err := tls.ConfigureHATLSKeystore()
if err != nil {
return fmt.Errorf("error loading tls keys: %w", err)
}
configFiles := map[string]string{
"/run/10-native-ha-instance.ini": "/etc/mqm/10-native-ha-instance.ini.tpl",
}
if haCertLabel != "" || haGroupCertLabel != "" {
configFiles["/run/10-native-ha-keystore.ini"] = "/etc/mqm/10-native-ha-keystore.ini.tpl"
}
if envConfigPresent() {
log.Println("Configuring Native HA using values provided in environment variables")
configFiles["/run/10-native-ha.ini"] = "/etc/mqm/10-native-ha.ini.tpl"
}
return loadConfigAndGenerate(configFiles, fipsAvailable, haCertLabel, haGroupCertLabel, log)
}
func loadConfigAndGenerate(templateConfigs map[string]string, fipsAvailable bool, haCertLabel, haGroupCertLabel string, log *logger.Logger) error {
cfg, err := loadConfigFromEnv(log)
if err != nil {
return err
}
err = cfg.updateTLS(fipsAvailable, haCertLabel, haGroupCertLabel)
if err != nil {
return err
}
for outputPath, templateFile := range templateConfigs {
err := cfg.generate(templateFile, outputPath, log)
if err != nil {
return err
}
}
return nil
}
func envConfigPresent() bool {
checkVars := []string{
"MQ_NATIVE_HA_INSTANCE_0_NAME",
"MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS",
"MQ_NATIVE_HA_INSTANCE_1_NAME",
"MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS",
"MQ_NATIVE_HA_INSTANCE_2_NAME",
"MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS",
"MQ_NATIVE_HA_TLS",
"MQ_NATIVE_HA_CIPHERSPEC",
}
for _, checkVar := range checkVars {
if os.Getenv(checkVar) != "" {
return true
}
}
return false
}
func loadConfigFromEnv(log *logger.Logger) (*haConfig, error) {
cfg := &haConfig{
Name: os.Getenv("HOSTNAME"),
Instances: [3]haInstance{
{
Name: os.Getenv("MQ_NATIVE_HA_INSTANCE_0_NAME"),
ReplicationAddress: os.Getenv("MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS"),
},
{
Name: os.Getenv("MQ_NATIVE_HA_INSTANCE_1_NAME"),
ReplicationAddress: os.Getenv("MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS"),
},
{
Name: os.Getenv("MQ_NATIVE_HA_INSTANCE_2_NAME"),
ReplicationAddress: os.Getenv("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS"),
},
},
Group: haGroupConfig{
Local: haLocalGroupConfig{
Address: os.Getenv("MQ_NATIVE_HA_GROUP_LOCAL_ADDRESS"),
Name: os.Getenv("MQ_NATIVE_HA_GROUP_LOCAL_NAME"),
Role: os.Getenv("MQ_NATIVE_HA_GROUP_ROLE"),
},
Recovery: haRecoveryGroupConfig{
Address: os.Getenv("MQ_NATIVE_HA_GROUP_REPLICATION_ADDRESS"),
Name: os.Getenv("MQ_NATIVE_HA_GROUP_RECOVERY_NAME"),
Enabled: os.Getenv("MQ_NATIVE_HA_GROUP_RECOVERY_ENABLED") != "false",
},
CipherSpec: os.Getenv("MQ_NATIVE_HA_GROUP_CIPHERSPEC"),
},
CipherSpec: os.Getenv("MQ_NATIVE_HA_CIPHERSPEC"),
keyRepository: os.Getenv("MQ_NATIVE_HA_KEY_REPOSITORY"),
}
if cfg.Group.Recovery.Name == "" {
cfg.Group.Recovery.Enabled = false
}
return cfg, nil
}
type haConfig struct {
Name string
Instances [3]haInstance
Group haGroupConfig
haTLSEnabled bool
CipherSpec string
CertificateLabel string
keyRepository string
fipsAvailable bool
}
func (h haConfig) ShouldConfigureTLS() bool {
if h.haTLSEnabled {
return true
}
if h.Group.Local.Name != "" {
return true
}
return false
}
func (h haConfig) SSLFipsRequired() string {
return yesNo(h.fipsAvailable).String()
}
func (h *haConfig) updateTLS(fipsAvailable bool, haCertLabel, haGroupCertLabel string) error {
if haCertLabel != "" {
h.CertificateLabel = haCertLabel
h.haTLSEnabled = true
}
if haGroupCertLabel != "" {
h.Group.CertificateLabel = haGroupCertLabel
h.haTLSEnabled = true
}
h.fipsAvailable = fipsAvailable
return nil
}
func (h haConfig) generate(templatePath string, outputPath string, log *logger.Logger) error {
return mqtemplate.ProcessTemplateFile(templatePath, outputPath, h, log)
}
func (h haConfig) KeyRepository() string {
if h.keyRepository != "" {
return h.keyRepository
}
return "/run/runmqserver/ha/tls/key"
}
type haGroupConfig struct {
Local haLocalGroupConfig
Recovery haRecoveryGroupConfig
CipherSpec string
CertificateLabel string
}
type haLocalGroupConfig struct {
Name string
Role string
Address string
}
type haRecoveryGroupConfig struct {
Name string
Enabled yesNo
Address string
}
type haInstance struct {
Name string
ReplicationAddress string
}
type yesNo bool
func (yn yesNo) String() string {
if yn {
return "Yes"
}
return "No"
}

545
internal/ha/ha_test.go Normal file
View File

@@ -0,0 +1,545 @@
/*
© Copyright IBM Corporation 2024
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ha
import (
"bytes"
"embed"
"fmt"
"os"
"path"
"strings"
"testing"
"github.com/ibm-messaging/mq-container/pkg/logger"
)
//go:embed test_fixtures
var testFixtures embed.FS
func TestConfigFromEnv(t *testing.T) {
tests := []struct {
TestName string
env map[string]string
overrides testOverrides
expected haConfig
}{
{
TestName: "Minimal config",
env: map[string]string{
"HOSTNAME": "minimal-config",
"MQ_NATIVE_HA_INSTANCE_0_NAME": "minimal-config-instance0",
"MQ_NATIVE_HA_INSTANCE_1_NAME": "minimal-config-instance1",
"MQ_NATIVE_HA_INSTANCE_2_NAME": "minimal-config-instance2",
"MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS": "minimal-config-instance0(9145)",
"MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS": "minimal-config-instance1(9145)",
"MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS": "minimal-config-instance2(9145)",
},
expected: haConfig{
Name: "minimal-config",
Instances: [3]haInstance{
{"minimal-config-instance0", "minimal-config-instance0(9145)"},
{"minimal-config-instance1", "minimal-config-instance1(9145)"},
{"minimal-config-instance2", "minimal-config-instance2(9145)"},
},
},
},
{
TestName: "Full TLS config",
env: map[string]string{
"HOSTNAME": "tls-config",
"MQ_NATIVE_HA_INSTANCE_0_NAME": "tls-config-instance0",
"MQ_NATIVE_HA_INSTANCE_1_NAME": "tls-config-instance1",
"MQ_NATIVE_HA_INSTANCE_2_NAME": "tls-config-instance2",
"MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS": "tls-config-instance0(9145)",
"MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS": "tls-config-instance1(9145)",
"MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS": "tls-config-instance2(9145)",
"MQ_NATIVE_HA_TLS": "true",
"MQ_NATIVE_HA_CIPHERSPEC": "a-cipher-spec",
"MQ_NATIVE_HA_KEY_REPOSITORY": "/path/to/repository",
},
overrides: testOverrides{
certificateLabel: asRef("cert-label-here"),
fips: asRef(false),
},
expected: haConfig{
Name: "tls-config",
Instances: [3]haInstance{
{"tls-config-instance0", "tls-config-instance0(9145)"},
{"tls-config-instance1", "tls-config-instance1(9145)"},
{"tls-config-instance2", "tls-config-instance2(9145)"},
},
haTLSEnabled: true,
CipherSpec: "a-cipher-spec",
keyRepository: "/path/to/repository",
CertificateLabel: "cert-label-here", // From override
fipsAvailable: false, // From override
},
},
{
TestName: "Group TLS (live plain) config",
env: map[string]string{
"HOSTNAME": "group-live-plain-config",
"MQ_NATIVE_HA_INSTANCE_0_NAME": "group-live-plain-config0",
"MQ_NATIVE_HA_INSTANCE_1_NAME": "group-live-plain-config1",
"MQ_NATIVE_HA_INSTANCE_2_NAME": "group-live-plain-config2",
"MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS": "group-live-plain-config0(9145)",
"MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS": "group-live-plain-config1(9145)",
"MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS": "group-live-plain-config2(9145)",
"MQ_NATIVE_HA_CIPHERSPEC": "NULL",
"MQ_NATIVE_HA_KEY_REPOSITORY": "/path/to/repository",
"MQ_NATIVE_HA_GROUP_RECOVERY_ENABLED": "true",
"MQ_NATIVE_HA_GROUP_LOCAL_NAME": "alpha",
"MQ_NATIVE_HA_GROUP_RECOVERY_NAME": "beta",
"MQ_NATIVE_HA_GROUP_CIPHERSPEC": "ANY_TLS",
"MQ_NATIVE_HA_GROUP_ROLE": "Live",
"MQ_NATIVE_HA_GROUP_LOCAL_ADDRESS": "(4445)",
"MQ_NATIVE_HA_GROUP_REPLICATION_ADDRESS": "beta-address(4445)",
},
overrides: testOverrides{
groupCertificateLabel: asRef("recovery-cert-label-here"),
fips: asRef(false),
},
expected: haConfig{
Name: "group-live-plain-config",
Instances: [3]haInstance{
{"group-live-plain-config0", "group-live-plain-config0(9145)"},
{"group-live-plain-config1", "group-live-plain-config1(9145)"},
{"group-live-plain-config2", "group-live-plain-config2(9145)"},
},
Group: haGroupConfig{
Local: haLocalGroupConfig{
Name: "alpha",
Role: "Live",
Address: "(4445)",
},
Recovery: haRecoveryGroupConfig{
Name: "beta",
Enabled: true,
Address: "beta-address(4445)",
},
CertificateLabel: "recovery-cert-label-here", // From override
CipherSpec: "ANY_TLS",
},
CipherSpec: "NULL",
keyRepository: "/path/to/repository",
haTLSEnabled: true,
fipsAvailable: false, // From override
},
},
}
for _, test := range tests {
t.Run(test.TestName, func(t *testing.T) {
// Set environment for test
savedEnv := make([]string, len(os.Environ()))
copy(savedEnv, os.Environ())
defer func() {
os.Clearenv()
for _, env := range savedEnv {
parts := strings.SplitN(env, "=", 2)
os.Setenv(parts[0], parts[1])
}
}()
for key, value := range test.env {
os.Setenv(key, value)
}
testLogger, logBuffer, err := newTestLogger(test.TestName)
if err != nil {
t.Fatalf("Failed to create test logger: %s", err.Error())
}
if !envConfigPresent() {
t.Fatalf("Check for Native HA config by environment variable unexpectedly reported false")
}
// Load config from env
cfg, err := loadConfigFromEnv(testLogger)
t.Log(logBuffer.String())
if err != nil {
t.Fatalf("Loading config failed: %s", err.Error())
}
test.overrides.apply(cfg)
// Validate
if *cfg != test.expected {
t.Fatalf("Configuration does not match expected:\n\tExpected: %#v\n\tActual: %#v\n", test.expected, *cfg)
}
})
}
}
func TestCheckEnv(t *testing.T) {
tests := []struct {
name string
env map[string]string
expect bool
}{
{
name: "empty env",
expect: false,
},
{
name: "Native HA with external config",
env: map[string]string{
"HOSTNAME": "external-config",
"MQ_NATIVE_HA": "true",
},
expect: false,
},
{
name: "Native HA with env config",
env: map[string]string{
"MQ_NATIVE_HA": "true",
"MQ_NATIVE_HA_INSTANCE_0_NAME": "minimal-config-instance0",
"MQ_NATIVE_HA_INSTANCE_1_NAME": "minimal-config-instance1",
"MQ_NATIVE_HA_INSTANCE_2_NAME": "minimal-config-instance2",
"MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS": "minimal-config-instance0(9145)",
"MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS": "minimal-config-instance1(9145)",
"MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS": "minimal-config-instance2(9145)",
},
expect: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// Set environment for test
savedEnv := make([]string, len(os.Environ()))
copy(savedEnv, os.Environ())
defer func() {
os.Clearenv()
for _, env := range savedEnv {
parts := strings.SplitN(env, "=", 2)
os.Setenv(parts[0], parts[1])
}
}()
for key, value := range test.env {
os.Setenv(key, value)
}
actual := envConfigPresent()
if actual != test.expect {
t.Fatalf("Incorrect result from environment variable check (actual: %v != expected: %v)", actual, test.expect)
}
})
}
}
func TestTemplatingFromConfig(t *testing.T) {
// Helper function to turn pairs of strings into a map
templateListToMap := func(paths ...string) map[string]string {
templates := map[string]string{}
for i := 0; i+1 < len(paths); i += 2 {
input := path.Join("../../ha/", paths[i])
output := paths[i+1]
templates[input] = output
}
return templates
}
tests := []struct {
TestName string
config haConfig
templates map[string]string
}{
{
TestName: "MinimalConfig (no-FIPS)",
config: haConfig{
fipsAvailable: false,
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha.ini.tpl", "envcfg/minimal-config.ini",
),
}, {
TestName: "MinimalConfig (FIPS)",
config: haConfig{
fipsAvailable: true,
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/fips.ini",
"10-native-ha.ini.tpl", "envcfg/minimal-config.ini",
),
},
{
TestName: "Base TLS config (no FIPS)",
config: haConfig{
haTLSEnabled: true,
CertificateLabel: "baseTLS",
fipsAvailable: false,
},
templates: templateListToMap(
"10-native-ha.ini.tpl", "envcfg/minimal-config.ini",
),
},
{
TestName: "Base TLS config (with FIPS)",
config: haConfig{
haTLSEnabled: true,
CertificateLabel: "baseTLS",
fipsAvailable: true,
},
templates: templateListToMap(
"10-native-ha-keystore.ini.tpl", "keystore/ha-only.ini",
"10-native-ha.ini.tpl", "envcfg/minimal-config.ini",
),
},
{
TestName: "Full TLS config (no-fips)",
config: haConfig{
haTLSEnabled: true,
CipherSpec: "some-cipher",
keyRepository: "/an/overridden/keystore",
fipsAvailable: false,
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha-keystore.ini.tpl", "keystore/overridden-path.ini",
"10-native-ha.ini.tpl", "envcfg/tls-full.ini",
),
},
{
TestName: "Minimal live config",
config: haConfig{
Group: haGroupConfig{
Local: haLocalGroupConfig{
Name: "alpha",
Role: "Live",
},
Recovery: haRecoveryGroupConfig{
Name: "beta",
Enabled: true,
Address: "beta-address(4445)",
},
CertificateLabel: "recoveryTLS",
},
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha-keystore.ini.tpl", "keystore/group-only.ini",
"10-native-ha.ini.tpl", "envcfg/group-live-minimal.ini",
),
},
{
TestName: "Minimal recovery config",
config: haConfig{
Group: haGroupConfig{
Local: haLocalGroupConfig{
Name: "beta",
Role: "Recovery",
},
Recovery: haRecoveryGroupConfig{
Name: "alpha",
Enabled: true,
Address: "alpha-address(4445)",
},
CertificateLabel: "recoveryTLS",
},
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha-keystore.ini.tpl", "keystore/group-only.ini",
"10-native-ha.ini.tpl", "envcfg/group-recovery-minimal.ini",
),
},
{
TestName: "Group TLS (live plain) config",
config: haConfig{
Group: haGroupConfig{
Local: haLocalGroupConfig{
Name: "alpha",
Role: "Live",
Address: "(4445)",
},
Recovery: haRecoveryGroupConfig{
Name: "beta",
Enabled: true,
Address: "beta-address(4445)",
},
CertificateLabel: "recoveryTLS",
CipherSpec: "ANY_TLS",
},
CipherSpec: "NULL",
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha-keystore.ini.tpl", "keystore/group-only.ini",
"10-native-ha.ini.tpl", "envcfg/group-live-plain-ha.ini",
),
},
{
TestName: "Separate HA and Group TLS config",
config: haConfig{
Group: haGroupConfig{
Local: haLocalGroupConfig{
Name: "alpha",
Role: "Live",
Address: "(4445)",
},
Recovery: haRecoveryGroupConfig{
Name: "beta",
Enabled: true,
Address: "beta-address(4445)",
},
CertificateLabel: "recoveryTLS",
CipherSpec: "ANY_TLS",
},
CertificateLabel: "baseTLS",
CipherSpec: "NULL",
},
templates: templateListToMap(
"10-native-ha-instance.ini.tpl", "instance/no-fips.ini",
"10-native-ha-keystore.ini.tpl", "keystore/ha-group.ini",
"10-native-ha.ini.tpl", "envcfg/group-live-plain-ha.ini",
),
},
}
for _, test := range tests {
t.Run(test.TestName, func(t *testing.T) {
for templateFile, expectedFile := range test.templates {
t.Run(templateFile, func(t *testing.T) {
t.Logf(`Runing templating test "%s"`, test.TestName)
t.Logf(`Expected to match template "%s"`, expectedFile)
testLogger, logBuffer, err := newTestLogger(test.TestName)
if err != nil {
t.Fatalf("Failed to create test logger: %s", err.Error())
}
// Load test config
cfg := applyTestDefaults(test.config)
// Generate template
tempOutputPath, err := os.CreateTemp("", "")
if err != nil {
t.Fatalf("Failed to create temporary output file: %s", err.Error())
}
defer func() { _ = os.Remove(tempOutputPath.Name()) }()
err = cfg.generate(templateFile, tempOutputPath.Name(), testLogger)
t.Log(logBuffer.String())
if err != nil {
t.Fatalf("Processing template to config failed: %s", err.Error())
}
actual, err := os.ReadFile(tempOutputPath.Name())
if err != nil {
t.Fatalf("Failed to read '%s': %s", test.TestName, err.Error())
}
// Validate
assertIniMatch(t, string(actual), expectedFile)
})
}
})
}
}
func applyTestDefaults(testConfig haConfig) haConfig {
baseName := "test-config"
setIfBlank(&testConfig.Name, baseName)
for i := 0; i < 3; i++ {
instName := fmt.Sprintf("%s-instance%d", baseName, i)
replAddress := fmt.Sprintf("%s(9145)", instName)
setIfBlank(&testConfig.Instances[i].Name, instName)
setIfBlank(&testConfig.Instances[i].ReplicationAddress, replAddress)
}
return testConfig
}
func setIfBlank[T comparable](setting *T, val T) {
var zero T
if *setting == zero {
*setting = val
}
}
func assertIniMatch(t *testing.T, actual string, expectedResultName string) {
expectedContent, err := testFixtures.ReadFile(fmt.Sprintf("test_fixtures/%s", expectedResultName))
if err != nil {
t.Fatalf("Failed to read expected results file (%s): %s", expectedResultName, err.Error())
}
expectedLines := strings.Split(string(expectedContent), "\n")
actualLines := strings.Split(actual, "\n")
filterBlank := func(lines *[]string) {
n := 0
for i := 0; i < len(*lines); i++ {
if strings.TrimSpace((*lines)[i]) == "" {
continue
}
(*lines)[n] = (*lines)[i]
n++
}
*lines = (*lines)[0:n]
}
filterBlank(&expectedLines)
filterBlank(&actualLines)
maxLine := len(expectedLines)
if len(actualLines) > maxLine {
maxLine = len(actualLines)
}
for i := 0; i < maxLine; i++ {
actLine, expLine := "", ""
if i < len(actualLines) {
actLine = actualLines[i]
}
if i < len(expectedLines) {
expLine = expectedLines[i]
}
if actLine != expLine {
t.Fatalf("Template does not match\n\nFirst difference at line %d:\n\tExpected: %s\n\tActual : %s\n\nExpected:\n\t%s\n\nActual:\n\t%s", i+1, expLine, actLine, strings.Join(expectedLines, "\n\t"), strings.Join(actualLines, "\n\t"))
}
}
}
func newTestLogger(name string) (*logger.Logger, *bytes.Buffer, error) {
buffer := new(bytes.Buffer)
l, err := logger.NewLogger(buffer, true, false, name)
return l, buffer, err
}
type testOverrides struct {
certificateLabel *string
groupCertificateLabel *string
fips *bool
}
func (t testOverrides) apply(cfg *haConfig) {
if t.certificateLabel != nil {
cfg.CertificateLabel = *t.certificateLabel
cfg.haTLSEnabled = true
}
if t.groupCertificateLabel != nil {
cfg.Group.CertificateLabel = *t.groupCertificateLabel
cfg.haTLSEnabled = true
}
if t.fips != nil {
cfg.fipsAvailable = *t.fips
}
}
func asRef[T any](val T) *T {
ref := &val
return ref
}

View File

@@ -0,0 +1,16 @@
NativeHALocalInstance:
GroupName=alpha
GroupRole=Live
NativeHAInstance:
Name=test-config-instance0
ReplicationAddress=test-config-instance0(9145)
NativeHAInstance:
Name=test-config-instance1
ReplicationAddress=test-config-instance1(9145)
NativeHAInstance:
Name=test-config-instance2
ReplicationAddress=test-config-instance2(9145)
NativeHARecoveryGroup:
GroupName=beta
Enabled=Yes
ReplicationAddress=beta-address(4445)

View File

@@ -0,0 +1,19 @@
NativeHALocalInstance:
CipherSpec=NULL
GroupName=alpha
GroupCipherSpec=ANY_TLS
GroupRole=Live
GroupLocalAddress=(4445)
NativeHAInstance:
Name=test-config-instance0
ReplicationAddress=test-config-instance0(9145)
NativeHAInstance:
Name=test-config-instance1
ReplicationAddress=test-config-instance1(9145)
NativeHAInstance:
Name=test-config-instance2
ReplicationAddress=test-config-instance2(9145)
NativeHARecoveryGroup:
GroupName=beta
Enabled=Yes
ReplicationAddress=beta-address(4445)

View File

@@ -0,0 +1,16 @@
NativeHALocalInstance:
GroupName=beta
GroupRole=Recovery
NativeHAInstance:
Name=test-config-instance0
ReplicationAddress=test-config-instance0(9145)
NativeHAInstance:
Name=test-config-instance1
ReplicationAddress=test-config-instance1(9145)
NativeHAInstance:
Name=test-config-instance2
ReplicationAddress=test-config-instance2(9145)
NativeHARecoveryGroup:
GroupName=alpha
Enabled=Yes
ReplicationAddress=alpha-address(4445)

View File

@@ -0,0 +1,10 @@
NativeHALocalInstance:
NativeHAInstance:
Name=test-config-instance0
ReplicationAddress=test-config-instance0(9145)
NativeHAInstance:
Name=test-config-instance1
ReplicationAddress=test-config-instance1(9145)
NativeHAInstance:
Name=test-config-instance2
ReplicationAddress=test-config-instance2(9145)

View File

@@ -0,0 +1,11 @@
NativeHALocalInstance:
CipherSpec=some-cipher
NativeHAInstance:
Name=test-config-instance0
ReplicationAddress=test-config-instance0(9145)
NativeHAInstance:
Name=test-config-instance1
ReplicationAddress=test-config-instance1(9145)
NativeHAInstance:
Name=test-config-instance2
ReplicationAddress=test-config-instance2(9145)

View File

@@ -0,0 +1,3 @@
NativeHALocalInstance:
Name=test-config
SSLFipsRequired=Yes

View File

@@ -0,0 +1,3 @@
NativeHALocalInstance:
Name=test-config
SSLFipsRequired=No

View File

@@ -0,0 +1,3 @@
NativeHALocalInstance:
GroupCertificateLabel=recoveryTLS
KeyRepository=/run/runmqserver/ha/tls/key

View File

@@ -0,0 +1,4 @@
NativeHALocalInstance:
CertificateLabel=baseTLS
GroupCertificateLabel=recoveryTLS
KeyRepository=/run/runmqserver/ha/tls/key

View File

@@ -0,0 +1,3 @@
NativeHALocalInstance:
CertificateLabel=baseTLS
KeyRepository=/run/runmqserver/ha/tls/key

View File

@@ -0,0 +1,2 @@
NativeHALocalInstance:
KeyRepository=/an/overridden/keystore