diff --git a/cmd/runmqserver/main.go b/cmd/runmqserver/main.go index fa95caa..0ba885f 100644 --- a/cmd/runmqserver/main.go +++ b/cmd/runmqserver/main.go @@ -25,7 +25,6 @@ import ( "sync" "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/tls" "github.com/ibm-messaging/mq-container/pkg/containerruntimelogger" @@ -177,12 +176,6 @@ func doMain() error { return err } - err = mqinimerge.AddStanzas(name) - if err != nil { - logTermination(err) - return err - } - err = startQueueManager(name) if err != nil { logTermination(err) diff --git a/cmd/runmqserver/qmgr.go b/cmd/runmqserver/qmgr.go index 7f0c1e1..dabf753 100644 --- a/cmd/runmqserver/qmgr.go +++ b/cmd/runmqserver/qmgr.go @@ -228,7 +228,7 @@ func getQueueManagerDataDir(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 { args = append(args, "-ld", "/mnt/mqm-log/log") } diff --git a/internal/mqinimerge/mqat.ini b/internal/mqinimerge/mqat.ini deleted file mode 100644 index f36ce8a..0000000 --- a/internal/mqinimerge/mqat.ini +++ /dev/null @@ -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 \ No newline at end of file diff --git a/internal/mqinimerge/mqinimerge.go b/internal/mqinimerge/mqinimerge.go deleted file mode 100644 index 923ab03..0000000 --- a/internal/mqinimerge/mqinimerge.go +++ /dev/null @@ -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 -} diff --git a/internal/mqinimerge/mqinimerge_test.go b/internal/mqinimerge/mqinimerge_test.go deleted file mode 100644 index fd20abd..0000000 --- a/internal/mqinimerge/mqinimerge_test.go +++ /dev/null @@ -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) - } - } - }) - } -} diff --git a/internal/mqinimerge/qm.ini b/internal/mqinimerge/qm.ini deleted file mode 100644 index a344afe..0000000 --- a/internal/mqinimerge/qm.ini +++ /dev/null @@ -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 diff --git a/internal/mqinimerge/test1qm.ini b/internal/mqinimerge/test1qm.ini deleted file mode 100644 index 7c0b393..0000000 --- a/internal/mqinimerge/test1qm.ini +++ /dev/null @@ -1,5 +0,0 @@ -ApiExitLocal:    - Sequence=1 - Function=EntryPoint - Module=/opt/mqm/exitlib.so - Name=mylib \ No newline at end of file diff --git a/internal/mqinimerge/test2qm.ini b/internal/mqinimerge/test2qm.ini deleted file mode 100644 index 734f9d9..0000000 --- a/internal/mqinimerge/test2qm.ini +++ /dev/null @@ -1,7 +0,0 @@ -AllActivityTrace: - ActivityInterval=11 - ActivityCount=1 - TraceLevel=INFO -ApplicationTrace: - ApplName=amqsget - Trace=ON \ No newline at end of file diff --git a/internal/mqinimerge/test3qm.ini b/internal/mqinimerge/test3qm.ini deleted file mode 100644 index 46e57f6..0000000 --- a/internal/mqinimerge/test3qm.ini +++ /dev/null @@ -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 diff --git a/test/docker/docker_api_test.go b/test/docker/docker_api_test.go index 445d47d..b9a075d 100644 --- a/test/docker/docker_api_test.go +++ b/test/docker/docker_api_test.go @@ -804,6 +804,187 @@ func TestInvalidMQSC(t *testing.T) { 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 // 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.