Added docker tests to test the new crtmqm -ii option (#50)
* Added docker tests to test the new crtmqm -ii option, removed the old ini merging code * Fixed issues with docket tests for ctrqmq -ii * Removed unneeded logging
This commit is contained in:
committed by
GitHub Enterprise
parent
28b723d6cf
commit
140db42675
@@ -25,7 +25,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/metrics"
|
"github.com/ibm-messaging/mq-container/internal/metrics"
|
||||||
"github.com/ibm-messaging/mq-container/internal/mqinimerge"
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||||
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
||||||
@@ -177,12 +176,6 @@ func doMain() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mqinimerge.AddStanzas(name)
|
|
||||||
if err != nil {
|
|
||||||
logTermination(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = startQueueManager(name)
|
err = startQueueManager(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ func getQueueManagerDataDir(mounts map[string]string, name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getCreateQueueManagerArgs(mounts map[string]string, name string) []string {
|
func getCreateQueueManagerArgs(mounts map[string]string, name string) []string {
|
||||||
args := []string{"-q", "-p", "1414"}
|
args := []string{"-ii", "/etc/mqm/", "-q", "-p", "1414"}
|
||||||
if _, ok := mounts["/mnt/mqm-log"]; ok {
|
if _, ok := mounts["/mnt/mqm-log"]; ok {
|
||||||
args = append(args, "-ld", "/mnt/mqm-log/log")
|
args = append(args, "-ld", "/mnt/mqm-log/log")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#*******************************************************************#
|
|
||||||
#* Module Name: mqat.ini *#
|
|
||||||
#* Type : IBM MQ queue manager configuration file *#
|
|
||||||
# Function : Define the configuration of application activity *#
|
|
||||||
#* trace for a single queue manager. *#
|
|
||||||
#*******************************************************************#
|
|
||||||
|
|
||||||
# Global settings stanza, default values
|
|
||||||
AllActivityTrace:
|
|
||||||
ActivityInterval=1
|
|
||||||
ActivityCount=100
|
|
||||||
TraceLevel=MEDIUM
|
|
||||||
TraceMessageData=0
|
|
||||||
StopOnGetTraceMsg=ON
|
|
||||||
SubscriptionDelivery=BATCHED
|
|
||||||
|
|
||||||
# Prevent the sample activity trace program from generating data
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsact*
|
|
||||||
Trace=OFF
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
© Copyright IBM Corporation 2018, 2019
|
|
||||||
|
|
||||||
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 mqinimerge merges user-supplied INI files into qm.ini and mqat.ini
|
|
||||||
package mqinimerge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/pkg/mqini"
|
|
||||||
)
|
|
||||||
|
|
||||||
var qmgrDir string
|
|
||||||
|
|
||||||
var stanzasQMINI []string
|
|
||||||
var stanzasMQATINI []string
|
|
||||||
|
|
||||||
// AddStanzas reads supplied MQ INI configuration files and updates the stanzas
|
|
||||||
// in the queue manager's INI configuration files.
|
|
||||||
func AddStanzas(qmname string) error {
|
|
||||||
// Find the qmgr directory.
|
|
||||||
qm, err := mqini.GetQueueManager(qmname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
qmgrDir = mqini.GetDataDirectory(qm)
|
|
||||||
// Find the users ini configuration file
|
|
||||||
files, err := getIniFileList()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(files) > 1 {
|
|
||||||
msg := fmt.Sprintf("[ %v ]", files)
|
|
||||||
return errors.New("Only a single INI file can be provided. Following INI files were found:" + msg)
|
|
||||||
}
|
|
||||||
if len(files) == 0 {
|
|
||||||
// No INI file update required.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//read user supplied config file.
|
|
||||||
iniFileBytes, err := ioutil.ReadFile(files[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
if len(userconfig) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare a list of all supported stanzas
|
|
||||||
PopulateAllAvailableStanzas()
|
|
||||||
|
|
||||||
// Update the qmgr ini file with user config.
|
|
||||||
qminiConfiglist, qmatConfiglist, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writeConfigStanzas(qminiConfiglist, qmatConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PopulateAllAvailableStanzas initializes the INI stanzas prescribed by MQ specification.
|
|
||||||
func PopulateAllAvailableStanzas() {
|
|
||||||
stanzasQMINI = []string{"ExitPath",
|
|
||||||
"Log",
|
|
||||||
"Service",
|
|
||||||
"ServiceComponent",
|
|
||||||
"Channels",
|
|
||||||
"TCP",
|
|
||||||
"ApiExitLocal",
|
|
||||||
"AccessMode",
|
|
||||||
"RestrictedMode",
|
|
||||||
"XAResourceManager",
|
|
||||||
"DefaultBindType",
|
|
||||||
"SSL",
|
|
||||||
"DiagnosticMessages",
|
|
||||||
"Filesystem",
|
|
||||||
"Security",
|
|
||||||
"TuningParameters",
|
|
||||||
"ExitPropertiesLocal",
|
|
||||||
"LU62",
|
|
||||||
"NETBIOS"}
|
|
||||||
|
|
||||||
stanzasMQATINI = []string{"AllActivityTrace", "ApplicationTrace"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIniFileList checks for the user supplied INI file in `/etc/mqm` directory.
|
|
||||||
func getIniFileList() ([]string, error) {
|
|
||||||
fileList := []string{}
|
|
||||||
err := filepath.Walk("/etc/mqm", func(path string, f os.FileInfo, err error) error {
|
|
||||||
if strings.HasSuffix(path, ".ini") {
|
|
||||||
fileList = append(fileList, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return fileList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareConfigStanzasToWrite Reads through the user supplied INI config file and prepares list of
|
|
||||||
// updates to be written into corresponding mq ini files (qm.ini and/or mqat.ini files)
|
|
||||||
func PrepareConfigStanzasToWrite(userconfig string) ([]string, []string, error) {
|
|
||||||
var qminiConfigStr string
|
|
||||||
var mqatiniConfigStr string
|
|
||||||
|
|
||||||
//read the initial version.
|
|
||||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
|
||||||
iniFileBytes, err := ioutil.ReadFile(filepath.Join(qmgrDir, "qm.ini"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
qminiConfigStr = string(iniFileBytes)
|
|
||||||
qminiConfiglist := strings.Split(qminiConfigStr, "\n")
|
|
||||||
|
|
||||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
|
||||||
iniFileBytes, err = ioutil.ReadFile(filepath.Join(qmgrDir, "mqat.ini"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
mqatiniConfigStr = string(iniFileBytes)
|
|
||||||
qmatConfiglist := strings.Split(mqatiniConfigStr, "\n")
|
|
||||||
|
|
||||||
stanzaListMerge := make(map[string]strings.Builder)
|
|
||||||
stanzaListAppend := make(map[string]strings.Builder)
|
|
||||||
var sbAppend strings.Builder
|
|
||||||
var sbMerger strings.Builder
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(strings.NewReader(userconfig))
|
|
||||||
scanner.Split(bufio.ScanLines)
|
|
||||||
consumetoAppend := false
|
|
||||||
consumeToMerge := false
|
|
||||||
var stanza string
|
|
||||||
|
|
||||||
// Read through the user file and prepare what we want.
|
|
||||||
for scanner.Scan() {
|
|
||||||
//if this is comment or an empty line, ignore it.
|
|
||||||
if strings.HasPrefix(scanner.Text(), "#") || len(strings.TrimSpace(scanner.Text())) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//thumb rule - all stanzas have ":".
|
|
||||||
if strings.Contains(scanner.Text(), ":") {
|
|
||||||
stanza = strings.TrimSpace(scanner.Text())
|
|
||||||
consumetoAppend = false
|
|
||||||
consumeToMerge = false
|
|
||||||
|
|
||||||
// Check if this stanza exists in the qm.ini/mqat.ini files
|
|
||||||
if strings.Contains(qminiConfigStr, stanza) ||
|
|
||||||
(strings.Contains(mqatiniConfigStr, stanza) && !(strings.Contains(stanza, "ApplicationTrace"))) {
|
|
||||||
consumeToMerge = true
|
|
||||||
sbMerger = strings.Builder{}
|
|
||||||
|
|
||||||
stanzaListMerge[stanza] = sbMerger
|
|
||||||
} else {
|
|
||||||
consumetoAppend = true
|
|
||||||
sbAppend = strings.Builder{}
|
|
||||||
stanzaListAppend[stanza] = sbAppend
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if consumetoAppend {
|
|
||||||
sb := stanzaListAppend[stanza]
|
|
||||||
_, err := sb.WriteString(scanner.Text() + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
stanzaListAppend[stanza] = sb
|
|
||||||
}
|
|
||||||
if consumeToMerge {
|
|
||||||
sb := stanzaListMerge[stanza]
|
|
||||||
_, err := sb.WriteString(scanner.Text() + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
stanzaListMerge[stanza] = sb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do merge.
|
|
||||||
if len(stanzaListMerge) > 0 {
|
|
||||||
for key := range stanzaListMerge {
|
|
||||||
toWrite, filename := ValidateStanzaToWrite(key)
|
|
||||||
if toWrite {
|
|
||||||
attrList := stanzaListMerge[key]
|
|
||||||
switch filename {
|
|
||||||
case "qm.ini":
|
|
||||||
qminiConfiglist, err = prepareStanzasToMerge(key, attrList, qminiConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
case "mqat.ini":
|
|
||||||
qmatConfiglist, err = prepareStanzasToMerge(key, attrList, qmatConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do append.
|
|
||||||
if len(stanzaListAppend) > 0 {
|
|
||||||
for key := range stanzaListAppend {
|
|
||||||
attrList := stanzaListAppend[key]
|
|
||||||
if strings.Contains(strings.Join(stanzasMQATINI, ", "), strings.TrimSuffix(strings.TrimSpace(key), ":")) {
|
|
||||||
qmatConfiglist = prepareStanzasToAppend(key, attrList, qmatConfiglist)
|
|
||||||
} else {
|
|
||||||
qminiConfiglist = prepareStanzasToAppend(key, attrList, qminiConfiglist)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return qminiConfiglist, qmatConfiglist, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateStanzaToWrite validates stanza to be written and the file it belongs to.
|
|
||||||
func ValidateStanzaToWrite(stanza string) (bool, string) {
|
|
||||||
stanza = strings.TrimSuffix(strings.TrimSpace(stanza), ":")
|
|
||||||
if strings.Contains(strings.Join(stanzasQMINI, ", "), stanza) {
|
|
||||||
return true, "qm.ini"
|
|
||||||
} else if strings.Contains(strings.Join(stanzasMQATINI, ", "), stanza) {
|
|
||||||
return true, "mqat.ini"
|
|
||||||
} else {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepareStanzasToAppend Prepares list of stanzas that are to be appended into qm ini files(qm.ini/mqat.ini)
|
|
||||||
func prepareStanzasToAppend(key string, attrList strings.Builder, iniConfigList []string) []string {
|
|
||||||
newVal := key + "\n" + attrList.String()
|
|
||||||
list := strings.Split(newVal, "\n")
|
|
||||||
iniConfigList = append(iniConfigList, list...)
|
|
||||||
return iniConfigList
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepareStanzasToMerge Prepares list of stanzas that are to be updated into qm ini files(qm.ini/mqat.ini)
|
|
||||||
// These stanzas are already present in mq ini files and their values have to be updated with user supplied ini.
|
|
||||||
func prepareStanzasToMerge(key string, attrList strings.Builder, iniConfigList []string) ([]string, error) {
|
|
||||||
|
|
||||||
pos := -1
|
|
||||||
//find the index of current stanza in qm's ini file.
|
|
||||||
for i := 0; i < len(iniConfigList); i++ {
|
|
||||||
if strings.Contains(iniConfigList[i], key) {
|
|
||||||
pos = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var appList strings.Builder
|
|
||||||
lineScanner := bufio.NewScanner(strings.NewReader(attrList.String()))
|
|
||||||
lineScanner.Split(bufio.ScanLines)
|
|
||||||
|
|
||||||
//Now go through the array and merge the values.
|
|
||||||
for lineScanner.Scan() {
|
|
||||||
attrLine := lineScanner.Text()
|
|
||||||
keyvalue := strings.Split(attrLine, "=")
|
|
||||||
merged := false
|
|
||||||
for i := pos + 1; i < len(iniConfigList); i++ {
|
|
||||||
if strings.HasPrefix(iniConfigList[i], "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.Contains(iniConfigList[i], ":") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if strings.Contains(iniConfigList[i], keyvalue[0]) {
|
|
||||||
iniConfigList[i] = attrLine
|
|
||||||
merged = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If this is not merged, then its a new parameter in existing stanza.
|
|
||||||
if !merged && len(strings.TrimSpace(attrLine)) > 0 {
|
|
||||||
_, err := appList.WriteString(attrLine)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
merged = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(appList.String()) > 0 {
|
|
||||||
temp := make([]string, pos+1)
|
|
||||||
for i := 0; i < pos+1; i++ {
|
|
||||||
temp[i] = iniConfigList[i]
|
|
||||||
}
|
|
||||||
list := strings.Split(appList.String(), "\n")
|
|
||||||
temp = append(temp, list...)
|
|
||||||
temp1 := iniConfigList[pos+1:]
|
|
||||||
iniConfigList = append(temp, temp1...)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return iniConfigList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeFileIfChanged writes the specified data to the specified file path
|
|
||||||
// (just like ioutil.WriteFile), but first checks if this is needed
|
|
||||||
func writeFileIfChanged(path string, data []byte, perm os.FileMode) error {
|
|
||||||
// #nosec G304 - internal utility using file name derived from dspmqinf
|
|
||||||
current, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Only write the new file if the it's different from the current file
|
|
||||||
if !bytes.Equal(current, data) {
|
|
||||||
err = ioutil.WriteFile(path, data, perm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeConfigStanzas writes the INI file updates into corresponding MQ INI files.
|
|
||||||
func writeConfigStanzas(qmConfig []string, atConfig []string) error {
|
|
||||||
err := writeFileIfChanged(filepath.Join(qmgrDir, "qm.ini"), []byte(strings.Join(qmConfig, "\n")), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = writeFileIfChanged(filepath.Join(qmgrDir, "mqat.ini"), []byte(strings.Join(atConfig, "\n")), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
© Copyright IBM Corporation 2018, 2019
|
|
||||||
|
|
||||||
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 mqinimerge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIniFileStanzas(t *testing.T) {
|
|
||||||
PopulateAllAvailableStanzas()
|
|
||||||
|
|
||||||
checkReturns("ApiExitLocal", true, true, t)
|
|
||||||
checkReturns("Channels", true, true, t)
|
|
||||||
checkReturns("TCP", true, true, t)
|
|
||||||
checkReturns("ServiceComponent", true, true, t)
|
|
||||||
checkReturns("Service", true, true, t)
|
|
||||||
checkReturns("AccessMode", true, true, t)
|
|
||||||
checkReturns("RestrictedMode", true, true, t)
|
|
||||||
checkReturns("XAResourceManager", true, true, t)
|
|
||||||
checkReturns("SSL", true, true, t)
|
|
||||||
checkReturns("Security", true, true, t)
|
|
||||||
checkReturns("TuningParameters", true, true, t)
|
|
||||||
checkReturns("ABC", false, false, t)
|
|
||||||
checkReturns("#1234ABD", true, false, t)
|
|
||||||
checkReturns("AllActivityTrace", false, true, t)
|
|
||||||
checkReturns("ApplicationTrace", false, true, t)
|
|
||||||
checkReturns("xyz123abvc", false, false, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile1Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Unexpected stanza file update: mqat.ini[%s]\n", atConfig)
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we want this line to be present exactly one.
|
|
||||||
for _, item := range qmConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "mylib") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile2Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test2qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we want this line to be present exactly one.
|
|
||||||
for _, item := range atConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "amqsget") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=amqsget, Config:%s\n", strings.Join(atConfig, "\n"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile3Update(t *testing.T) {
|
|
||||||
i := 0
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test3qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Unexpected stanza file update: qm.ini[%s]\n", atConfig)
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
qmConfigStr := strings.Join(qmConfig, "\n")
|
|
||||||
atConfigStr := strings.Join(atConfig, "\n")
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(strings.NewReader(userconfig))
|
|
||||||
scanner.Split(bufio.ScanLines)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
i++
|
|
||||||
//first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file.
|
|
||||||
if i < 20 {
|
|
||||||
if !strings.Contains(qmConfigStr, strings.TrimSpace(line)) {
|
|
||||||
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfigStr)
|
|
||||||
}
|
|
||||||
} else if i > 20 {
|
|
||||||
if !strings.Contains(atConfigStr, line) {
|
|
||||||
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, atConfigStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile4Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
//First merge
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
//second merge.
|
|
||||||
qmConfig, atConfig, err = PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we just did a double merge, however we want this line to be present exactly one.
|
|
||||||
for _, item := range qmConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "mylib") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) {
|
|
||||||
exists, filename := ValidateStanzaToWrite(stanza)
|
|
||||||
if exists != shouldexist {
|
|
||||||
t.Errorf("Stanza should exist %t but found was %t", shouldexist, exists)
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldexist {
|
|
||||||
if isqmini {
|
|
||||||
if filename != "qm.ini" {
|
|
||||||
t.Errorf("Expected filename:qm.ini for stanza:%s. But got %s", stanza, filename)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if filename != "mqat.ini" {
|
|
||||||
t.Errorf("Expected filename:mqat.ini for stanza:%s. But got %s", stanza, filename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var writeFileIfChangedTests = []struct {
|
|
||||||
before []byte
|
|
||||||
after []byte
|
|
||||||
same bool
|
|
||||||
}{
|
|
||||||
{[]byte("ABC€"), []byte("ABC€"), true},
|
|
||||||
{[]byte("ABC€"), []byte("ABC$"), false},
|
|
||||||
{[]byte("ABC€"), []byte("BBC€"), false},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteFileIfChanged(t *testing.T) {
|
|
||||||
tmpFile := filepath.Join(os.TempDir(), t.Name())
|
|
||||||
t.Logf("Using temp file %v", tmpFile)
|
|
||||||
for i, table := range writeFileIfChangedTests {
|
|
||||||
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
|
|
||||||
err := ioutil.WriteFile(tmpFile, table.before, 0600)
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
defer os.Remove(tmpFile)
|
|
||||||
fi, err := os.Stat(tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
beforeMod := fi.ModTime()
|
|
||||||
err = writeFileIfChanged(tmpFile, table.after, 0600)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
fi, err = os.Stat(tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
afterMod := fi.ModTime()
|
|
||||||
if table.same {
|
|
||||||
if beforeMod != afterMod {
|
|
||||||
t.Errorf("Expected file timestamps to be the same (%v); got %v", beforeMod, afterMod)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if beforeMod == afterMod {
|
|
||||||
t.Errorf("Expected file timestamp to be different got %v and %v", beforeMod, afterMod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#*******************************************************************#
|
|
||||||
#* Module Name: qm.ini *#
|
|
||||||
#* Type : IBM MQ queue manager configuration file *#
|
|
||||||
# Function : Define the configuration of a single queue manager *#
|
|
||||||
#* *#
|
|
||||||
#*******************************************************************#
|
|
||||||
#* Notes : *#
|
|
||||||
#* 1) This file defines the configuration of the queue manager *#
|
|
||||||
#* *#
|
|
||||||
#*******************************************************************#
|
|
||||||
ExitPath:
|
|
||||||
ExitsDefaultPath=C:\ProgramData\IBM\MQ\exits
|
|
||||||
ExitsDefaultPath64=C:\ProgramData\IBM\MQ\exits64
|
|
||||||
InstanceData:
|
|
||||||
InstanceID=1562831591
|
|
||||||
Startup=ServiceManual
|
|
||||||
#* *#
|
|
||||||
#* *#
|
|
||||||
Log:
|
|
||||||
LogPrimaryFiles=3
|
|
||||||
LogSecondaryFiles=2
|
|
||||||
LogFilePages=4096
|
|
||||||
LogType=CIRCULAR
|
|
||||||
LogBufferPages=0
|
|
||||||
LogPath=C:\ProgramData\IBM\MQ\log\INI1\
|
|
||||||
LogWriteIntegrity=TripleWrite
|
|
||||||
Service:
|
|
||||||
Name=AuthorizationService
|
|
||||||
EntryPoints=14
|
|
||||||
ServiceComponent:
|
|
||||||
Service=AuthorizationService
|
|
||||||
Name=MQSeries.WindowsNT.auth.service
|
|
||||||
Module=amqzfu.dll
|
|
||||||
ComponentDataSize=0
|
|
||||||
Channels:
|
|
||||||
ChlauthEarlyAdopt=Y
|
|
||||||
TCP:
|
|
||||||
SndBuffSize=0
|
|
||||||
RcvBuffSize=0
|
|
||||||
RcvSndBuffSize=0
|
|
||||||
RcvRcvBuffSize=0
|
|
||||||
ClntSndBuffSize=0
|
|
||||||
ClntRcvBuffSize=0
|
|
||||||
SvrSndBuffSize=0
|
|
||||||
SvrRcvBuffSize=0
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ApiExitLocal:
|
|
||||||
Sequence=1
|
|
||||||
Function=EntryPoint
|
|
||||||
Module=/opt/mqm/exitlib.so
|
|
||||||
Name=mylib
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
AllActivityTrace:
|
|
||||||
ActivityInterval=11
|
|
||||||
ActivityCount=1
|
|
||||||
TraceLevel=INFO
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsget
|
|
||||||
Trace=ON
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
ApiExitLocal:
|
|
||||||
Sequence=1
|
|
||||||
Function=EntryPoint
|
|
||||||
Module=/opt/foo/foo.so
|
|
||||||
Name=FooExit
|
|
||||||
Channels:
|
|
||||||
MQIBindType=FASTPATH
|
|
||||||
Log:
|
|
||||||
LogPrimaryFiles=30
|
|
||||||
LogType=CIRCULAR
|
|
||||||
LogPath=/ProgramfILES/IBM/MQ/log/INI1/
|
|
||||||
TCP:
|
|
||||||
SndBuffSize=4095
|
|
||||||
RcvBuffSize=4095
|
|
||||||
RcvSndBuffSize=4095
|
|
||||||
RcvRcvBuffSize=4095
|
|
||||||
ClntSndBuffSize=2049
|
|
||||||
ClntRcvBuffSize=2049
|
|
||||||
SvrSndBuffSize=2049
|
|
||||||
SvrRcvBuffSize=2049
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsput
|
|
||||||
Trace=ON
|
|
||||||
@@ -804,6 +804,187 @@ func TestInvalidMQSC(t *testing.T) {
|
|||||||
expectTerminationMessage(t, cli, id)
|
expectTerminationMessage(t, cli, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimpleMQIniMerge(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var files = []struct {
|
||||||
|
Name, Body string
|
||||||
|
}{
|
||||||
|
{"Dockerfile", fmt.Sprintf(`
|
||||||
|
FROM %v
|
||||||
|
USER root
|
||||||
|
ADD test1.ini /etc/mqm/
|
||||||
|
RUN chmod 0660 /etc/mqm/test1.ini
|
||||||
|
USER mqm`, imageName())},
|
||||||
|
{"test1.ini",
|
||||||
|
"Log:\n LogSecondaryFiles=28"},
|
||||||
|
}
|
||||||
|
tag := createImage(t, cli, files)
|
||||||
|
defer deleteImage(t, cli, tag)
|
||||||
|
|
||||||
|
containerConfig := container.Config{
|
||||||
|
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||||
|
Image: tag,
|
||||||
|
}
|
||||||
|
id := runContainer(t, cli, &containerConfig)
|
||||||
|
defer cleanContainer(t, cli, id)
|
||||||
|
waitForReady(t, cli, id)
|
||||||
|
|
||||||
|
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||||
|
_, test := execContainer(t, cli, id, "mqm", []string{"bash", "-c", catIniFileCommand})
|
||||||
|
merged := strings.Contains(test, "LogSecondaryFiles=28")
|
||||||
|
|
||||||
|
if !merged {
|
||||||
|
t.Error("ERROR: The Files are not merged correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func TestMultipleIniMerge(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var files = []struct {
|
||||||
|
Name, Body string
|
||||||
|
}{
|
||||||
|
{"Dockerfile", fmt.Sprintf(`
|
||||||
|
FROM %v
|
||||||
|
USER root
|
||||||
|
ADD test1.ini /etc/mqm/
|
||||||
|
ADD test2.ini /etc/mqm/
|
||||||
|
ADD test3.ini /etc/mqm/
|
||||||
|
RUN chmod 0660 /etc/mqm/test1.ini
|
||||||
|
RUN chmod 0660 /etc/mqm/test2.ini
|
||||||
|
RUN chmod 0660 /etc/mqm/test3.ini
|
||||||
|
USER mqm`, imageName())},
|
||||||
|
{"test1.ini",
|
||||||
|
"Log:\n LogSecondaryFiles=28"},
|
||||||
|
{"test2.ini",
|
||||||
|
"Log:\n LogSecondaryFiles=28"},
|
||||||
|
{"test3.ini",
|
||||||
|
"ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF"},
|
||||||
|
}
|
||||||
|
tag := createImage(t, cli, files)
|
||||||
|
defer deleteImage(t, cli, tag)
|
||||||
|
|
||||||
|
containerConfig := container.Config{
|
||||||
|
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||||
|
Image: tag,
|
||||||
|
}
|
||||||
|
id := runContainer(t, cli, &containerConfig)
|
||||||
|
defer cleanContainer(t, cli, id)
|
||||||
|
waitForReady(t, cli, id)
|
||||||
|
|
||||||
|
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||||
|
_, test := execContainer(t, cli, id, "mqm", []string{"bash", "-c", catIniFileCommand})
|
||||||
|
|
||||||
|
//checks that no duplicates are created by adding 2 ini files with the same line
|
||||||
|
numberOfDuplicates := strings.Count(test, "LogSecondaryFiles=28")
|
||||||
|
|
||||||
|
newStanza := strings.Contains(test, "ApplicationTrace:\n ApplName=amqsact*")
|
||||||
|
|
||||||
|
if (numberOfDuplicates > 1) || !newStanza {
|
||||||
|
t.Error("ERROR: The Files are not merged correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMQIniMergeOnTheSameVolumeButTwoContainers(t *testing.T) {
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var filesFirstContainer = []struct {
|
||||||
|
Name, Body string
|
||||||
|
}{
|
||||||
|
{"Dockerfile", fmt.Sprintf(`
|
||||||
|
FROM %v
|
||||||
|
USER root
|
||||||
|
ADD test1.ini /etc/mqm/
|
||||||
|
RUN chmod 0660 /etc/mqm/test1.ini
|
||||||
|
USER mqm`, imageName())},
|
||||||
|
{"test1.ini",
|
||||||
|
"ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF"},
|
||||||
|
}
|
||||||
|
firstImage := createImage(t, cli, filesFirstContainer)
|
||||||
|
defer deleteImage(t, cli, firstImage)
|
||||||
|
vol := createVolume(t, cli, t.Name())
|
||||||
|
defer removeVolume(t, cli, vol.Name)
|
||||||
|
|
||||||
|
containerConfig := container.Config{
|
||||||
|
Image: firstImage,
|
||||||
|
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
hostConfig := container.HostConfig{
|
||||||
|
Binds: []string{
|
||||||
|
coverageBind(t),
|
||||||
|
vol.Name + ":/mnt/mqm",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
networkingConfig := network.NetworkingConfig{}
|
||||||
|
ctr1, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
startContainer(t, cli, ctr1.ID)
|
||||||
|
waitForReady(t, cli, ctr1.ID)
|
||||||
|
|
||||||
|
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||||
|
_, test := execContainer(t, cli, ctr1.ID, "mqm", []string{"bash", "-c", catIniFileCommand})
|
||||||
|
addedStanza := strings.Contains(test, "ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF")
|
||||||
|
|
||||||
|
if addedStanza != true {
|
||||||
|
t.Error("ERROR: The Files are not merged correctly")
|
||||||
|
}
|
||||||
|
// Delete the first container
|
||||||
|
cleanContainer(t, cli, ctr1.ID)
|
||||||
|
|
||||||
|
var filesSecondContainer = []struct {
|
||||||
|
Name, Body string
|
||||||
|
}{
|
||||||
|
{"Dockerfile", fmt.Sprintf(`
|
||||||
|
FROM %v
|
||||||
|
USER root
|
||||||
|
ADD test1.ini /etc/mqm/
|
||||||
|
RUN chmod 0660 /etc/mqm/test1.ini
|
||||||
|
USER mqm`, imageName())},
|
||||||
|
{"test1.ini",
|
||||||
|
"Log:\n LogFilePages=5000"},
|
||||||
|
}
|
||||||
|
|
||||||
|
secondImage := createImage(t, cli, filesSecondContainer)
|
||||||
|
defer deleteImage(t, cli, secondImage)
|
||||||
|
|
||||||
|
containerConfig2 := container.Config{
|
||||||
|
Image: secondImage,
|
||||||
|
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctr2, err := cli.ContainerCreate(context.Background(), &containerConfig2, &hostConfig, &networkingConfig, t.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer cleanContainer(t, cli, ctr2.ID)
|
||||||
|
startContainer(t, cli, ctr2.ID)
|
||||||
|
waitForReady(t, cli, ctr2.ID)
|
||||||
|
|
||||||
|
_, test2 := execContainer(t, cli, ctr2.ID, "mqm", []string{"bash", "-c", catIniFileCommand})
|
||||||
|
changedStanza := strings.Contains(test2, "LogFilePages=5000")
|
||||||
|
//check if stanza that was merged in the first container doesnt exist in this one.
|
||||||
|
firstMergedStanza := strings.Contains(test2, "ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF")
|
||||||
|
|
||||||
|
if !changedStanza || firstMergedStanza {
|
||||||
|
t.Error("ERROR: The Files are not merged correctly after removing first container")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// TestReadiness creates a new image with large amounts of MQSC in, to
|
// TestReadiness creates a new image with large amounts of MQSC in, to
|
||||||
// ensure that the readiness check doesn't pass until configuration has finished.
|
// ensure that the readiness check doesn't pass until configuration has finished.
|
||||||
// WARNING: This test is sensitive to the speed of the machine it's running on.
|
// WARNING: This test is sensitive to the speed of the machine it's running on.
|
||||||
|
|||||||
Reference in New Issue
Block a user