Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ MQ_VERSION ?= 9.0.4.0
# be installed. The default value is derived from MQ_VERSION, BASE_IMAGE and architecture
# Does not apply to MQ Advanced for Developers.
MQ_ARCHIVE ?= IBM_MQ_$(MQ_VERSION)_$(MQ_ARCHIVE_TYPE)_$(MQ_ARCHIVE_ARCH).tar.gz
# MQ_ARCHIVE_DEV is the name of the file, under the downloads directory, from which MQ Advanced
# for Developers can be installed
MQ_ARCHIVE_DEV ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
# Options to `go test` for the Docker tests
TEST_OPTS_DOCKER ?=
# Options to `go test` for the Kubernetes tests
Expand Down Expand Up @@ -68,9 +71,6 @@ endif
# Archive names for IBM MQ Advanced for Developers for Ubuntu
MQ_ARCHIVE_DEV_9.0.3.0=mqadv_dev903_ubuntu_x86-64.tar.gz
MQ_ARCHIVE_DEV_9.0.4.0=mqadv_dev904_ubuntu_x86-64.tar.gz
# MQ_ARCHIVE_DEV is the name of the file, under the downloads directory, from which MQ Advanced
# for Developers can be installed
MQ_ARCHIVE_DEV=$(MQ_ARCHIVE_DEV_$(MQ_VERSION))

###############################################################################
# Build targets
Expand Down Expand Up @@ -134,13 +134,13 @@ test-unit:

.PHONY: test-advancedserver
test-advancedserver: test/docker/vendor
$(info $(SPACER)$(shell printf $(TITLE)"Test $(DOCKER_FULL_ADVANCEDSERVER) on Docker"$(END)))
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_ADVANCEDSERVER) on Docker"$(END)))
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER) go test -parallel $(NUM_CPU) $(TEST_OPTS_DOCKER)

.PHONY: test-devserver
test-devserver: test/docker/vendor
$(info $(SPACER)$(shell printf $(TITLE)"Test $(DOCKER_FULL_DEVSERVER) on Docker"$(END)))
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER) go test -parallel $(NUM_CPU) $(TEST_OPTS_DOCKER)
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_DEVSERVER) on Docker"$(END)))
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER) go test -parallel $(NUM_CPU) -tags mqdev $(TEST_OPTS_DOCKER)

.PHONY: test-advancedserver-cover
test-advancedserver-cover: test/docker/vendor
Expand Down Expand Up @@ -218,11 +218,13 @@ build-advancedserver: downloads/$(MQ_ARCHIVE) docker-version
$(call docker-build-mq,$(MQ_IMAGE_ADVANCEDSERVER),Dockerfile-server,$(MQ_ARCHIVE),"4486e8c4cc9146fd9b3ce1f14a2dfc5b","IBM MQ Advanced",$(MQ_VERSION))

.PHONY: build-devserver
# Target-specific variable to add web server into devserver image
build-devserver: MQ_PACKAGES=ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-ams ibmmq-web
build-devserver: downloads/$(MQ_ARCHIVE_DEV) docker-version
@test "$(shell uname -m)" = "x86_64" || (echo "Error: MQ Advanced for Developers is only available for x86_64 architecture" && exit 1)
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER_BASE)"$(END)))
$(call docker-build-mq,$(MQ_IMAGE_DEVSERVER_BASE),Dockerfile-server,$(MQ_ARCHIVE_DEV),"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers (Non-Warranted)",$(MQ_VERSION))
docker build --tag $(MQ_IMAGE_DEVSERVER) incubating/mqadvanced-server-dev
docker build --tag $(MQ_IMAGE_DEVSERVER) --file incubating/mqadvanced-server-dev/Dockerfile .

.PHONY: build-advancedserver-cover
build-advancedserver-cover: docker-version
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ In order to use the image, it is necessary to accept the terms of the IBM MQ lic
* **LICENSE** - Set this to `accept` to agree to the MQ Advanced for Developers license. If you wish to see the license you can set this to `view`.
* **LANG** - Set this to the language you would like the license to be printed in.
* **MQ_QMGR_NAME** - Set this to the name you want your Queue Manager to be created with.
* **LOG_FORMAT** - Set this to change the format of the logs which are printed on the container's stdout. Set to "json" to use JSON format (JSON object per line); set to "basic" to use a simple human-readable. Defaults to "basic".
* **LOG_FORMAT** - Set this to change the format of the logs which are printed on the container's stdout. Set to "json" to use JSON format (JSON object per line); set to "basic" to use a simple human-readable format. Defaults to "basic".


# Issues and contributions
Expand Down
145 changes: 145 additions & 0 deletions cmd/runmqdevserver/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
© Copyright IBM Corporation 2018

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 main

import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"syscall"

"github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/internal/logger"
"github.com/ibm-messaging/mq-container/internal/name"
)

var log *logger.Logger

func setPassword(user string, password string) error {
cmd := exec.Command("chpasswd")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
fmt.Fprintf(stdin, "%s:%s", user, password)
stdin.Close()
_, _, err = command.RunCmd(cmd)
if err != nil {
return err
}
log.Printf("Set password for \"%v\" user", user)
return nil
}

func getLogFormat() string {
return os.Getenv("LOG_FORMAT")
}

func getDebug() bool {
debug := os.Getenv("DEBUG")
if debug == "true" || debug == "1" {
return true
}
return false
}

func configureLogger() error {
var err error
f := getLogFormat()
d := getDebug()
n, err := name.GetQueueManagerName()
if err != nil {
return err
}
switch f {
case "json":
log, err = logger.NewLogger(os.Stderr, d, true, n)
if err != nil {
return err
}
case "basic":
log, err = logger.NewLogger(os.Stderr, d, false, n)
if err != nil {
return err
}
default:
log, err = logger.NewLogger(os.Stdout, d, false, n)
return fmt.Errorf("invalid value for LOG_FORMAT: %v", f)
}
return nil
}

func logTerminationf(format string, args ...interface{}) {
logTermination(fmt.Sprintf(format, args))
}

// TODO: Duplicated code
func logTermination(args ...interface{}) {
msg := fmt.Sprint(args)
// Write the message to the termination log. This is the default place
// that Kubernetes will look for termination information.
log.Debugf("Writing termination message: %v", msg)
err := ioutil.WriteFile("/dev/termination-log", []byte(msg), 0660)
if err != nil {
log.Debug(err)
}
log.Error(msg)
}

func doMain() error {
err := configureLogger()
if err != nil {
logTermination(err)
return err
}
adminPassword, set := os.LookupEnv("MQ_ADMIN_PASSWORD")
if set {
err = setPassword("admin", adminPassword)
if err != nil {
logTerminationf("Error setting admin password: %v", err)
return err
}
}
appPassword, set := os.LookupEnv("MQ_APP_PASSWORD")
if set {
err = setPassword("app", appPassword)
if err != nil {
logTerminationf("Error setting app password: %v", err)
return err
}
}

err = updateMQSC(set)
if err != nil {
logTerminationf("Error updating MQSC: %v", err)
return err
}

return nil
}

var osExit = os.Exit

func main() {
err := doMain()
if err != nil {
osExit(1)
} else {
// Replace this process with runmqserver
syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver"}, os.Environ())
}
}
57 changes: 57 additions & 0 deletions cmd/runmqdevserver/mqsc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
© Copyright IBM Corporation 2018

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 main

import (
"html/template"
"os"
)

func updateMQSC(appPasswordRequired bool) error {
var checkClient string
if appPasswordRequired {
checkClient = "REQUIRED"
} else {
checkClient = "ASQMGR"
}
const mqsc string = "/etc/mqm/dev.mqsc"
if os.Getenv("MQ_DEV") == "true" {
const mqscTemplate string = mqsc + ".tpl"
// Re-configure channel if app password not set
t, err := template.ParseFiles(mqscTemplate)
if err != nil {
log.Error(err)
return err
}
f, err := os.OpenFile(mqsc, os.O_CREATE|os.O_WRONLY, 0660)
defer f.Close()
err = t.Execute(f, map[string]string{"ChckClnt": checkClient})
if err != nil {
log.Error(err)
return err
}
// TODO: Lookup value for MQM user here?
err = os.Chown(mqsc, 999, 999)
if err != nil {
log.Error(err)
return err
}
// os.Remove(mqscTemplate)
} else {
os.Remove(mqsc)
}
return nil
}
18 changes: 14 additions & 4 deletions cmd/runmqserver/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,33 @@ func getDebug() bool {
return false
}

func configureLogger() (mirrorFunc, error) {
func configureLogger(name string) (mirrorFunc, error) {
var err error
f := getLogFormat()
d := getDebug()
switch f {
case "json":
log = logger.NewLogger(os.Stderr, d, true)
log, err = logger.NewLogger(os.Stderr, d, true, name)
if err != nil {
return nil, err
}
return log.LogDirect, nil
case "basic":
log = logger.NewLogger(os.Stderr, d, false)
log, err = logger.NewLogger(os.Stderr, d, false, name)
if err != nil {
return nil, err
}
return func(msg string) {
// Parse the JSON message, and print a simplified version
var obj map[string]interface{}
json.Unmarshal([]byte(msg), &obj)
fmt.Printf(formatSimple(obj["ibm_datetime"].(string), obj["message"].(string)))
}, nil
default:
log = logger.NewLogger(os.Stdout, d, false)
log, err = logger.NewLogger(os.Stdout, d, false, name)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("invalid value for LOG_FORMAT: %v", f)
}
}
14 changes: 10 additions & 4 deletions cmd/runmqserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ import (
)

func doMain() error {
mf, err := configureLogger()
name, nameErr := name.GetQueueManagerName()
mf, err := configureLogger(name)
if err != nil {
logTermination(err)
return err
}
err = ready.Clear()
if err != nil {
if nameErr != nil {
logTermination(err)
return err
}
name, err := name.GetQueueManagerName()
err = ready.Clear()
if err != nil {
logTermination(err)
return err
Expand Down Expand Up @@ -68,6 +68,12 @@ func doMain() error {
if err != nil {
return err
}

err = postInit(name)
if err != nil {
return err
}

newQM, err := createQueueManager(name)
if err != nil {
logTermination(err)
Expand Down
2 changes: 1 addition & 1 deletion cmd/runmqserver/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const filename = "/var/coverage/exitCode"

func init() {
test = flag.Bool("test", false, "Set to true when running tests for coverage")
log = logger.NewLogger(os.Stdout, true, false)
log, _ = logger.NewLogger(os.Stdout, true, false, "test")
}

// Test started when the test binary is started. Only calls main.
Expand Down
4 changes: 3 additions & 1 deletion cmd/runmqserver/mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ func mirrorAvailableMessages(f *os.File, mf mirrorFunc) {
mf(t)
count++
}
log.Debugf("Mirrored %v log entries from %v", count, f.Name())
if count > 0 {
log.Debugf("Mirrored %v log entries from %v", count, f.Name())
}
err := scanner.Err()
if err != nil {
log.Errorf("Error reading file %v: %v", f.Name(), err)
Expand Down
36 changes: 36 additions & 0 deletions cmd/runmqserver/post_init_dev.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// +build mqdev

/*
© Copyright IBM Corporation 2018

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 main

import "os"

// postInit is run after /var/mqm is set up
// This version of postInit is only included as part of the MQ Advanced for Developers build
func postInit(name string) error {
disable := os.Getenv("MQ_DISABLE_WEB_CONSOLE")
if disable != "true" && disable != "1" {
// Configure and start the web server, in the background (if installed)
// WARNING: No error handling or health checking available for the web server,
// which is why it's limited to use with MQ Advanced for Developers only
go func() {
configureWebServer()
startWebServer()
}()
}
return nil
}
Loading