diff --git a/Dockerfile-server b/Dockerfile-server index 80d656b..513fc80 100644 --- a/Dockerfile-server +++ b/Dockerfile-server @@ -34,6 +34,7 @@ RUN chmod a+x /usr/local/bin/install-mq.sh \ WORKDIR /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/ COPY cmd/ ./cmd COPY internal/ ./internal +COPY pkg/ ./pkg COPY vendor/ ./vendor ENV PATH="${PATH}:/opt/rh/go-toolset-7/root/usr/bin" \ CGO_CFLAGS="-I/opt/mqm/inc/" \ @@ -46,6 +47,7 @@ RUN go test -v ./cmd/runmqdevserver/... RUN go test -v ./cmd/runmqserver/ RUN go test -v ./cmd/chkmqready/ RUN go test -v ./cmd/chkmqhealthy/ +RUN go test -v ./pkg/... RUN go test -v ./internal/... RUN go vet ./cmd/... ./internal/... diff --git a/cmd/chkmqhealthy/main.go b/cmd/chkmqhealthy/main.go index 65e10c9..623a554 100644 --- a/cmd/chkmqhealthy/main.go +++ b/cmd/chkmqhealthy/main.go @@ -23,7 +23,7 @@ import ( "os/exec" "strings" - "github.com/ibm-messaging/mq-container/internal/name" + "github.com/ibm-messaging/mq-container/pkg/name" ) func queueManagerHealthy() (bool, error) { diff --git a/cmd/chkmqready/main.go b/cmd/chkmqready/main.go index c1f06fe..9bc5487 100644 --- a/cmd/chkmqready/main.go +++ b/cmd/chkmqready/main.go @@ -22,8 +22,8 @@ import ( "net" "os" - "github.com/ibm-messaging/mq-container/internal/name" "github.com/ibm-messaging/mq-container/internal/ready" + "github.com/ibm-messaging/mq-container/pkg/name" ) func main() { diff --git a/cmd/runmqdevserver/main.go b/cmd/runmqdevserver/main.go index 6070538..0007b56 100644 --- a/cmd/runmqdevserver/main.go +++ b/cmd/runmqdevserver/main.go @@ -23,10 +23,10 @@ import ( "syscall" "github.com/ibm-messaging/mq-container/internal/command" - "github.com/ibm-messaging/mq-container/internal/containerruntimelogger" - "github.com/ibm-messaging/mq-container/internal/logger" "github.com/ibm-messaging/mq-container/internal/mqtemplate" - "github.com/ibm-messaging/mq-container/internal/name" + "github.com/ibm-messaging/mq-container/pkg/containerruntimelogger" + "github.com/ibm-messaging/mq-container/pkg/logger" + "github.com/ibm-messaging/mq-container/pkg/name" ) var log *logger.Logger @@ -172,7 +172,7 @@ func main() { } else { // Replace this process with runmqserver // #nosec G204 - err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-dev"}, os.Environ()) + err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-nologruntime", "-dev"}, os.Environ()) if err != nil { log.Errorf("Error replacing this process with runmqserver: %v", err) } diff --git a/cmd/runmqserver/logging.go b/cmd/runmqserver/logging.go index b27eb74..aa455f5 100644 --- a/cmd/runmqserver/logging.go +++ b/cmd/runmqserver/logging.go @@ -27,8 +27,8 @@ import ( "sync" "github.com/ibm-messaging/mq-container/internal/command" - "github.com/ibm-messaging/mq-container/internal/logger" - "github.com/ibm-messaging/mq-container/internal/mqini" + "github.com/ibm-messaging/mq-container/pkg/logger" + "github.com/ibm-messaging/mq-container/pkg/mqini" ) // var debug = false diff --git a/cmd/runmqserver/main.go b/cmd/runmqserver/main.go index 1eca829..fa95caa 100644 --- a/cmd/runmqserver/main.go +++ b/cmd/runmqserver/main.go @@ -24,18 +24,19 @@ import ( "os" "sync" - "github.com/ibm-messaging/mq-container/internal/containerruntimelogger" "github.com/ibm-messaging/mq-container/internal/metrics" - "github.com/ibm-messaging/mq-container/internal/name" + "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/internal/mqini" + "github.com/ibm-messaging/mq-container/pkg/containerruntimelogger" + "github.com/ibm-messaging/mq-container/pkg/name" ) func doMain() error { var initFlag = flag.Bool("i", false, "initialize volume only, then exit") var infoFlag = flag.Bool("info", false, "Display debug info, then exit") - var devFlag = flag.Bool("dev", false, "used when running this program from runmqdevserver to control log output") + var noLogRuntimeFlag = flag.Bool("nologruntime", false, "used when running this program from another program, to control log output") + var devFlag = flag.Bool("dev", false, "used when running this program from runmqdevserver to control how TLS is configured") flag.Parse() name, nameErr := name.GetQueueManagerName() @@ -88,7 +89,7 @@ func doMain() error { // Enable diagnostic collecting on failure collectDiagOnFail = true - if *devFlag == false { + if *noLogRuntimeFlag == false { err = containerruntimelogger.LogContainerDetails(log) if err != nil { logTermination(err) @@ -176,7 +177,7 @@ func doMain() error { return err } - err = mqini.AddStanzas(name) + err = mqinimerge.AddStanzas(name) if err != nil { logTermination(err) return err diff --git a/cmd/runmqserver/main_test.go b/cmd/runmqserver/main_test.go index 6059174..52aba1a 100644 --- a/cmd/runmqserver/main_test.go +++ b/cmd/runmqserver/main_test.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2017, 2018 +© Copyright IBM Corporation 2017, 2019 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import ( "strconv" "testing" - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" ) var test *bool diff --git a/internal/metrics/exporter.go b/internal/metrics/exporter.go index 9c06cd9..2afeb3e 100644 --- a/internal/metrics/exporter.go +++ b/internal/metrics/exporter.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2018 +© 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. @@ -18,7 +18,7 @@ limitations under the License. package metrics import ( - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" "github.com/prometheus/client_golang/prometheus" ) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index f14fb60..7e661fe 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -23,7 +23,7 @@ import ( "net/http" "time" - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/ready" "github.com/prometheus/client_golang/prometheus" ) diff --git a/internal/metrics/update.go b/internal/metrics/update.go index f2f470a..ac68230 100644 --- a/internal/metrics/update.go +++ b/internal/metrics/update.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2018 +© 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. @@ -22,7 +22,7 @@ import ( "strings" "time" - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-golang/ibmmq" "github.com/ibm-messaging/mq-golang/mqmetric" ) diff --git a/internal/metrics/update_test.go b/internal/metrics/update_test.go index 82e8874..52900e8 100644 --- a/internal/metrics/update_test.go +++ b/internal/metrics/update_test.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2018 +© 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. @@ -19,7 +19,7 @@ import ( "os" "testing" - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-golang/mqmetric" ) diff --git a/internal/mqini/mqat.ini b/internal/mqinimerge/mqat.ini similarity index 100% rename from internal/mqini/mqat.ini rename to internal/mqinimerge/mqat.ini diff --git a/internal/mqini/mqini.go b/internal/mqinimerge/mqinimerge.go similarity index 66% rename from internal/mqini/mqini.go rename to internal/mqinimerge/mqinimerge.go index 2490ef0..4d4c10e 100644 --- a/internal/mqini/mqini.go +++ b/internal/mqinimerge/mqinimerge.go @@ -15,7 +15,7 @@ limitations under the License. */ // Package mqini provides information about queue managers -package mqini +package mqinimerge import ( "bufio" @@ -27,92 +27,35 @@ import ( "regexp" "strings" - "github.com/ibm-messaging/mq-container/internal/command" + "github.com/ibm-messaging/mq-container/pkg/mqini" ) -// QueueManager describe high-level configuration information for a queue manager -type QueueManager struct { - Name string - Prefix string - Directory string - DataPath string - InstallationName string -} - var qmgrDir string var stanzasQMINI []string var stanzasMQATINI []string -// getQueueManagerFromStanza parses a queue manager stanza -func getQueueManagerFromStanza(stanza string) (*QueueManager, error) { - scanner := bufio.NewScanner(strings.NewReader(stanza)) - qm := QueueManager{} - for scanner.Scan() { - l := scanner.Text() - l = strings.TrimSpace(l) - t := strings.Split(l, "=") - switch t[0] { - case "Name": - qm.Name = t[1] - case "Prefix": - qm.Prefix = t[1] - case "Directory": - qm.Directory = t[1] - case "DataPath": - qm.DataPath = t[1] - case "InstallationName": - qm.InstallationName = t[1] - } - } - return &qm, scanner.Err() -} - -// GetQueueManager returns queue manager configuration information -func GetQueueManager(name string) (*QueueManager, error) { - // dspmqinf essentially returns a subset of mqs.ini, but it's simpler to parse - out, _, err := command.Run("dspmqinf", "-o", "stanza", name) - if err != nil { - return nil, err - } - return getQueueManagerFromStanza(out) -} - -// GetErrorLogDirectory returns the directory holding the error logs for the -// specified queue manager -func GetErrorLogDirectory(qm *QueueManager) string { - if qm.DataPath != "" { - return filepath.Join(qm.DataPath, "errors") - } - return filepath.Join(qm.Prefix, "qmgrs", qm.Directory, "errors") -} - -//AddStanzas Reads supplied mq ini configuration files and updates the stanzas -//into queue manager's ini configuration files. +// 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 := GetQueueManager(qmname) + // Find the qmgr directory. + qm, err := mqini.GetQueueManager(qmname) if err != nil { return err } - qmgrDir = filepath.Join(qm.Prefix, "qmgrs", qm.Directory) - if qm.DataPath != "" { - qmgrDir = qm.DataPath - } - - //Find the users ini configuration file + 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 are found:" + msg) + 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. + // No INI file update required. return nil } @@ -125,10 +68,10 @@ func AddStanzas(qmname string) error { return nil } - //Prepare a list of all supported stanzas + // Prepare a list of all supported stanzas PopulateAllAvailableStanzas() - //Update the qmgr ini file with user config. + // Update the qmgr ini file with user config. qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig) if err != nil { return err @@ -141,7 +84,7 @@ func AddStanzas(qmname string) error { return nil } -// PopulateAllAvailableStanzas initializes the ini stanzas prescribed by mq specification. +// PopulateAllAvailableStanzas initializes the INI stanzas prescribed by MQ specification. func PopulateAllAvailableStanzas() { stanzasQMINI = []string{"ExitPath", "Log", @@ -166,9 +109,8 @@ func PopulateAllAvailableStanzas() { stanzasMQATINI = []string{"AllActivityTrace", "ApplicationTrace"} } -// getIniFileList Checks for the user supplied ini file in /etc/mqm directory. +// 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") { @@ -182,10 +124,9 @@ func getIniFileList() ([]string, error) { 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.) +// 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 @@ -215,13 +156,13 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) { consumeToMerge := false var stanza string - //read through the user file and prepare what we want. + // Read through the user file and prepare what we want. for scanner.Scan() { if strings.Contains(scanner.Text(), ":") { consumetoAppend = false consumeToMerge = false stanza = scanner.Text() - //check if this stanza exists in the qm.ini/mqat.ini files + // 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 @@ -253,7 +194,7 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) { } } - //merge if stanza exits. + // Merge if stanza exits if len(stanzaListMerge) > 0 { for key := range stanzaListMerge { toWrite, filename := ValidateStanzaToWrite(key) @@ -270,7 +211,7 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) { } } - //append new stanzas. + // Append new stanzas. if len(stanzaListAppend) > 0 { for key := range stanzaListAppend { attrList := stanzaListAppend[key] @@ -285,7 +226,7 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) { return qminiConfigStr, mqatiniConfigStr, nil } -//ValidateStanzaToWrite Validates stanza to be written and the file it belongs to. +// ValidateStanzaToWrite validates stanza to be written and the file it belongs to. func ValidateStanzaToWrite(stanza string) (bool, string) { stanza = strings.TrimSpace(stanza) if strings.Contains(stanza, ":") { @@ -301,26 +242,27 @@ func ValidateStanzaToWrite(stanza string) (bool, string) { } } -//prepareStanzasToAppend Prepares list of stanzas that are to be appended into qm ini files(qm.ini/mqat.ini) +// 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, iniConfig string) string { newVal := key + "\n" + attrList.String() iniConfig = iniConfig + newVal return iniConfig } -//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. +// 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, iniConfig string) string { lineScanner := bufio.NewScanner(strings.NewReader(attrList.String())) lineScanner.Split(bufio.ScanLines) for lineScanner.Scan() { attrLine := lineScanner.Text() keyvalue := strings.Split(attrLine, "=") - //this line present in qm.ini, update value. + // This line present in qm.ini, update value. if strings.Contains(iniConfig, keyvalue[0]) { re := regexp.MustCompile(keyvalue[0] + "=.*") iniConfig = re.ReplaceAllString(iniConfig, attrLine) - } else { //this line not present in qm.ini file, add it. + } else { + // This line not present in qm.ini file, add it. re := regexp.MustCompile(key) newVal := key + "\n" + attrLine iniConfig = re.ReplaceAllString(iniConfig, newVal) @@ -329,9 +271,8 @@ func prepareStanzasToMerge(key string, attrList strings.Builder, iniConfig strin return iniConfig } -//writeConfigStanzas Writes the ini file updates into corresponding mq ini files. +// writeConfigStanzas writes the INI file updates into corresponding mq ini files. func writeConfigStanzas(qmConfig string, atConfig string) error { - err := ioutil.WriteFile(filepath.Join(qmgrDir, "qm.ini"), []byte(qmConfig), 0644) if err != nil { return err diff --git a/internal/mqini/mqini_test.go b/internal/mqinimerge/mqinimerge_test.go similarity index 79% rename from internal/mqini/mqini_test.go rename to internal/mqinimerge/mqinimerge_test.go index 95e85d4..2af3fb2 100644 --- a/internal/mqini/mqini_test.go +++ b/internal/mqinimerge/mqinimerge_test.go @@ -13,7 +13,7 @@ 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 mqini +package mqinimerge import ( "bufio" @@ -22,49 +22,6 @@ import ( "testing" ) -var getQueueManagerTests = []struct { - file string - name string - prefix string - directory string - errorLogDir string -}{ - {"dspmqinf1.txt", "foo", "/var/mqm", "foo", "/var/mqm/qmgrs/foo/errors"}, - {"dspmqinf2.txt", "a/b", "/var/mqm", "a&b", "/var/mqm/qmgrs/a&b/errors"}, - {"dspmqinf3.txt", "..", "/var/mqm", "!!", "/var/mqm/qmgrs/!!/errors"}, -} - -func TestGetQueueManager(t *testing.T) { - for _, table := range getQueueManagerTests { - t.Run(table.file, func(t *testing.T) { - b, err := ioutil.ReadFile(table.file) - if err != nil { - t.Fatal(err) - } - qm, err := getQueueManagerFromStanza(string(b)) - if err != nil { - t.Fatal(err) - } - t.Logf("%#v", qm) - if qm.Name != table.name { - t.Errorf("Expected name=%v; got %v", table.name, qm.Name) - } - if qm.Prefix != table.prefix { - t.Errorf("Expected prefix=%v; got %v", table.prefix, qm.Prefix) - } - if qm.Directory != table.directory { - t.Errorf("Expected directory=%v; got %v", table.directory, qm.Directory) - } - - // Test - d := GetErrorLogDirectory(qm) - if d != table.errorLogDir { - t.Errorf("Expected error log directory=%v; got %v", table.errorLogDir, d) - } - }) - } -} - func TestIniFileStanzas(t *testing.T) { PopulateAllAvailableStanzas() @@ -87,7 +44,6 @@ func TestIniFileStanzas(t *testing.T) { } func TestIniFile1Update(t *testing.T) { - iniFileBytes, err := ioutil.ReadFile("test1qm.ini") if err != nil { t.Errorf("Unexpected error: [%s]\n", err.Error()) @@ -116,7 +72,6 @@ func TestIniFile1Update(t *testing.T) { } func TestIniFile2Update(t *testing.T) { - iniFileBytes, err := ioutil.ReadFile("test2qm.ini") if err != nil { t.Errorf("Unexpected error: [%s]\n", err.Error()) @@ -145,7 +100,6 @@ func TestIniFile2Update(t *testing.T) { } func TestIniFile3Update(t *testing.T) { - i := 0 iniFileBytes, err := ioutil.ReadFile("test3qm.ini") if err != nil { @@ -182,7 +136,6 @@ func TestIniFile3Update(t *testing.T) { } 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) diff --git a/internal/mqini/qm.ini b/internal/mqinimerge/qm.ini similarity index 100% rename from internal/mqini/qm.ini rename to internal/mqinimerge/qm.ini diff --git a/internal/mqini/test1qm.ini b/internal/mqinimerge/test1qm.ini similarity index 100% rename from internal/mqini/test1qm.ini rename to internal/mqinimerge/test1qm.ini diff --git a/internal/mqini/test2qm.ini b/internal/mqinimerge/test2qm.ini similarity index 100% rename from internal/mqini/test2qm.ini rename to internal/mqinimerge/test2qm.ini diff --git a/internal/mqini/test3qm.ini b/internal/mqinimerge/test3qm.ini similarity index 84% rename from internal/mqini/test3qm.ini rename to internal/mqinimerge/test3qm.ini index f745a68..46e57f6 100644 --- a/internal/mqini/test3qm.ini +++ b/internal/mqinimerge/test3qm.ini @@ -1,8 +1,8 @@ ApiExitLocal:    Sequence=1 Function=EntryPoint - Module=/opt/MQOpenTracing/MQOpenTracingExit.so - Name=MQOpenTracingExit + Module=/opt/foo/foo.so + Name=FooExit Channels: MQIBindType=FASTPATH Log: diff --git a/internal/mqtemplate/mqtemplate.go b/internal/mqtemplate/mqtemplate.go index ab4c71a..75e2062 100644 --- a/internal/mqtemplate/mqtemplate.go +++ b/internal/mqtemplate/mqtemplate.go @@ -23,7 +23,7 @@ import ( "text/template" "github.com/ibm-messaging/mq-container/internal/command" - "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-container/pkg/logger" ) // ProcessTemplateFile takes a Go templateFile, and processes it with the diff --git a/internal/containerruntimelogger/logruntime.go b/pkg/containerruntimelogger/logruntime.go similarity index 98% rename from internal/containerruntimelogger/logruntime.go rename to pkg/containerruntimelogger/logruntime.go index 1702eb5..1394768 100644 --- a/internal/containerruntimelogger/logruntime.go +++ b/pkg/containerruntimelogger/logruntime.go @@ -22,8 +22,8 @@ import ( "strings" "github.com/ibm-messaging/mq-container/internal/containerruntime" - "github.com/ibm-messaging/mq-container/internal/logger" "github.com/ibm-messaging/mq-container/internal/user" + "github.com/ibm-messaging/mq-container/pkg/logger" ) // LogContainerDetails logs details about the container runtime diff --git a/internal/logger/logger.go b/pkg/logger/logger.go similarity index 100% rename from internal/logger/logger.go rename to pkg/logger/logger.go diff --git a/internal/logger/logger_test.go b/pkg/logger/logger_test.go similarity index 97% rename from internal/logger/logger_test.go rename to pkg/logger/logger_test.go index 49d8e99..47c9287 100644 --- a/internal/logger/logger_test.go +++ b/pkg/logger/logger_test.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2018 +© 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. diff --git a/internal/mqini/dspmqinf1.txt b/pkg/mqini/dspmqinf1.txt similarity index 100% rename from internal/mqini/dspmqinf1.txt rename to pkg/mqini/dspmqinf1.txt diff --git a/internal/mqini/dspmqinf2.txt b/pkg/mqini/dspmqinf2.txt similarity index 100% rename from internal/mqini/dspmqinf2.txt rename to pkg/mqini/dspmqinf2.txt diff --git a/internal/mqini/dspmqinf3.txt b/pkg/mqini/dspmqinf3.txt similarity index 100% rename from internal/mqini/dspmqinf3.txt rename to pkg/mqini/dspmqinf3.txt diff --git a/pkg/mqini/mqini.go b/pkg/mqini/mqini.go new file mode 100644 index 0000000..9b8eae6 --- /dev/null +++ b/pkg/mqini/mqini.go @@ -0,0 +1,85 @@ +/* +© 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 mqini provides information about queue managers +package mqini + +import ( + "bufio" + "path/filepath" + "strings" + + "github.com/ibm-messaging/mq-container/internal/command" +) + +// QueueManager describe high-level configuration information for a queue manager +type QueueManager struct { + Name string + Prefix string + Directory string + DataPath string + InstallationName string +} + +// getQueueManagerFromStanza parses a queue manager stanza +func getQueueManagerFromStanza(stanza string) (*QueueManager, error) { + scanner := bufio.NewScanner(strings.NewReader(stanza)) + qm := QueueManager{} + for scanner.Scan() { + l := scanner.Text() + l = strings.TrimSpace(l) + t := strings.Split(l, "=") + switch t[0] { + case "Name": + qm.Name = t[1] + case "Prefix": + qm.Prefix = t[1] + case "Directory": + qm.Directory = t[1] + case "DataPath": + qm.DataPath = t[1] + case "InstallationName": + qm.InstallationName = t[1] + } + } + return &qm, scanner.Err() +} + +// GetQueueManager returns queue manager configuration information +func GetQueueManager(name string) (*QueueManager, error) { + // dspmqinf essentially returns a subset of mqs.ini, but it's simpler to parse + out, _, err := command.Run("dspmqinf", "-o", "stanza", name) + if err != nil { + return nil, err + } + return getQueueManagerFromStanza(out) +} + +// GetErrorLogDirectory returns the directory holding the error logs for the +// specified queue manager +func GetErrorLogDirectory(qm *QueueManager) string { + return filepath.Join(GetDataDirectory(qm), "errors") +} + +// GetDataDirectory returns the data directory for the specified queue manager +func GetDataDirectory(qm *QueueManager) string { + if qm.DataPath != "" { + // Data path has been set explicitly (e.g. for multi-instance queue manager) + return qm.DataPath + } else { + return filepath.Join(qm.Prefix, "qmgrs", qm.Directory) + } +} diff --git a/pkg/mqini/mqini_test.go b/pkg/mqini/mqini_test.go new file mode 100644 index 0000000..18aeaf7 --- /dev/null +++ b/pkg/mqini/mqini_test.go @@ -0,0 +1,64 @@ +/* +© 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 mqini + +import ( + "io/ioutil" + "testing" +) + +var getQueueManagerTests = []struct { + file string + name string + prefix string + directory string + errorLogDir string +}{ + {"dspmqinf1.txt", "foo", "/var/mqm", "foo", "/var/mqm/qmgrs/foo/errors"}, + {"dspmqinf2.txt", "a/b", "/var/mqm", "a&b", "/var/mqm/qmgrs/a&b/errors"}, + {"dspmqinf3.txt", "..", "/var/mqm", "!!", "/var/mqm/qmgrs/!!/errors"}, +} + +func TestGetQueueManager(t *testing.T) { + for _, table := range getQueueManagerTests { + t.Run(table.file, func(t *testing.T) { + b, err := ioutil.ReadFile(table.file) + if err != nil { + t.Fatal(err) + } + qm, err := getQueueManagerFromStanza(string(b)) + if err != nil { + t.Fatal(err) + } + t.Logf("%#v", qm) + if qm.Name != table.name { + t.Errorf("Expected name=%v; got %v", table.name, qm.Name) + } + if qm.Prefix != table.prefix { + t.Errorf("Expected prefix=%v; got %v", table.prefix, qm.Prefix) + } + if qm.Directory != table.directory { + t.Errorf("Expected directory=%v; got %v", table.directory, qm.Directory) + } + + // Test + d := GetErrorLogDirectory(qm) + if d != table.errorLogDir { + t.Errorf("Expected error log directory=%v; got %v", table.errorLogDir, d) + } + }) + } +} diff --git a/internal/name/name.go b/pkg/name/name.go similarity index 97% rename from internal/name/name.go rename to pkg/name/name.go index 0a97fd2..743c903 100644 --- a/internal/name/name.go +++ b/pkg/name/name.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2017 +© Copyright IBM Corporation 2017, 2019 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/internal/name/name_test.go b/pkg/name/name_test.go similarity index 97% rename from internal/name/name_test.go rename to pkg/name/name_test.go index c69cac0..68288c4 100644 --- a/internal/name/name_test.go +++ b/pkg/name/name_test.go @@ -1,5 +1,5 @@ /* -© Copyright IBM Corporation 2017 +© Copyright IBM Corporation 2017, 2019 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.