Compare commits

..

5 Commits

Author SHA1 Message Date
Rob Parker
1aab07c6ed set CipherSpec to ANY_TLS12 and refresh security (#362) 2019-08-28 17:01:15 +01:00
Luke Powlett
556ac6aec2 Update to UBI 7.7-98 2019-08-28 15:10:14 +01:00
Arthur Barr
950aecf300 Temporarily remove Docker 1.12 test in Travis 2019-08-28 14:21:40 +01:00
Arthur Barr
492c6876ca Use podman build if available 2019-08-28 14:21:40 +01:00
Luke Powlett
9896e53cba increment release in makefile 2019-08-07 16:02:46 +01:00
69 changed files with 723 additions and 1311 deletions

View File

@@ -18,7 +18,7 @@ sudo: required
language: go language: go
go: go:
- "1.12" - "1.10"
services: services:
- docker - docker
@@ -29,60 +29,49 @@ cache:
directories: directories:
- downloads - downloads
env:
global:
- RELEASE=""
jobs: jobs:
include: include:
- stage: build - stage: build and test
name: "Basic build"
if: branch != private-master AND tag IS blank
os: linux
env: env:
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_AMD64 - BASE_IMAGE=ubuntu:16.04
script: bash -e travis-build-scripts/run.sh - DOCKER_DOWNGRADE="echo nothing to be done"
- if: branch = private-master OR tag =~ ^pre-release* # TEMPORARY removal of Docker 1.12 test, due to errors from apt repository
name: "Multi-Arch AMD64 build" # - if: type IN (pull_request) OR tag IS present
os: linux # env:
env: # - BASE_IMAGE=ubuntu:16.04
- BUILD_ALL=true # - DOCKER_DOWNGRADE="docker save -o images.tar mqadvanced-server-dev mq-dev-jms-test &&
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_AMD64 # sudo apt-get autoremove -y docker-ce &&
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_AMD64 # curl -fsSL \"https://apt.dockerproject.org/gpg\" | sudo apt-key add - &&
script: bash -e travis-build-scripts/run.sh # sudo apt-add-repository \"deb https://apt.dockerproject.org/repo ubuntu-$(lsb_release -cs) main\" &&
- if: branch = private-master OR tag =~ ^pre-release* # sudo apt-get update &&
name: "Multi-Arch PPC64LE build" # sudo apt-get install docker-engine=1.12.6-0~ubuntu-$(lsb_release -cs) &&
os: linux-ppc64le # docker load -q -i images.tar &&
env: # export DOCKER_API_VERSION=\"1.24\""
- BUILD_ALL=true
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_PPC64LE
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_PPC64LE
script: bash -e travis-build-scripts/run.sh
- if: branch = private-master OR tag =~ ^pre-release*
name: "Multi-Arch S390X build"
os: linux-s390
env:
- BUILD_ALL=true
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_S390X
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_S390X
script: bash -e travis-build-scripts/run.sh
- stage: deploy
name: "Pre-release deploy"
if: tag =~ ^pre-release*
script: bash -e travis-build-scripts/release.sh staging
- name: "Production release deploy"
if: tag =~ ^production-release*
script: bash -e travis-build-scripts/release.sh production
before_install: before_install:
- make install-build-deps - ./install-build-deps-ubuntu.sh
install: install:
- echo nothing - echo nothing
before_script: echo nothing before_script:
- echo 'Downloading Go dependencies...' && echo -en 'travis_fold:start:deps\\r'
- make deps
- echo -en 'travis_fold:end:deps\\r'
- echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
- make build-devserver
- echo -en 'travis_fold:end:build-devserver\\r'
- echo 'Building Developer JMS test image...' && echo -en 'travis_fold:start:build-devjmstest\\r'
- make build-devjmstest
- echo -en 'travis_fold:end:build-devjmstest\\r'
script:
- echo 'Downgrading Docker (if necessary)...' && echo -en 'travis_fold:start:docker-downgrade\\r'
- eval "$DOCKER_DOWNGRADE"
- echo -en 'travis_fold:end:docker-downgrade\\r'
- echo 'Testing Developer image...' && echo -en 'travis_fold:start:test-devserver\\r'
- make test-devserver
- echo -en 'travis_fold:end:test-devserver\\r'
after_success: after_success:
- make lint - make lint

View File

@@ -1,11 +1,5 @@
# Change log # Change log
## 9.1.4.0 (2019-12-06)
* Updated to MQ version 9.1.4.0
* Updated to use UBI8 as base image
* Added required security settings to self signed certificates to align with macOS Catalina requirements
## 9.1.3.0 (2019-07-19) ## 9.1.3.0 (2019-07-19)
* Updated to MQ version 9.1.3.0 * Updated to MQ version 9.1.3.0

View File

@@ -12,12 +12,12 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
ARG BASE_IMAGE=registry.redhat.io/ubi8/ubi-minimal ARG BASE_IMAGE=registry.access.redhat.com/ubi7/ubi-minimal
ARG BASE_TAG=8.1-279 ARG BASE_TAG=7.7-98
############################################################################### ###############################################################################
# Build stage to build Go code # Build stage to build Go code
############################################################################### ###############################################################################
FROM registry.redhat.io/rhel8/go-toolset:1.12.8-11 as builder FROM registry.access.redhat.com/devtools/go-toolset-7-rhel7 as builder
# FROM docker.io/centos/go-toolset-7-centos7 as builder # FROM docker.io/centos/go-toolset-7-centos7 as builder
# The URL to download the MQ installer from in tar.gz format # The URL to download the MQ installer from in tar.gz format
# This assumes an archive containing the MQ RPM install packages # This assumes an archive containing the MQ RPM install packages
@@ -34,9 +34,8 @@ RUN chmod a+x /usr/local/bin/install-mq.sh \
WORKDIR /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/ WORKDIR /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/
COPY cmd/ ./cmd COPY cmd/ ./cmd
COPY internal/ ./internal COPY internal/ ./internal
COPY pkg/ ./pkg
COPY vendor/ ./vendor COPY vendor/ ./vendor
ENV PATH="${PATH}:/opt/rh/go-toolset-1.11/root/usr/bin" \ ENV PATH="${PATH}:/opt/rh/go-toolset-7/root/usr/bin" \
CGO_CFLAGS="-I/opt/mqm/inc/" \ CGO_CFLAGS="-I/opt/mqm/inc/" \
CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" CGO_LDFLAGS_ALLOW="-Wl,-rpath.*"
RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/ RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/
@@ -47,7 +46,6 @@ RUN go test -v ./cmd/runmqdevserver/...
RUN go test -v ./cmd/runmqserver/ RUN go test -v ./cmd/runmqserver/
RUN go test -v ./cmd/chkmqready/ RUN go test -v ./cmd/chkmqready/
RUN go test -v ./cmd/chkmqhealthy/ RUN go test -v ./cmd/chkmqhealthy/
RUN go test -v ./pkg/...
RUN go test -v ./internal/... RUN go test -v ./internal/...
RUN go vet ./cmd/... ./internal/... RUN go vet ./cmd/... ./internal/...
@@ -56,7 +54,7 @@ RUN go vet ./cmd/... ./internal/...
############################################################################### ###############################################################################
FROM $BASE_IMAGE:$BASE_TAG AS mq-server FROM $BASE_IMAGE:$BASE_TAG AS mq-server
# The MQ packages to install - see install-mq.sh for default value # The MQ packages to install - see install-mq.sh for default value
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev914_linux_x86-64.tar.gz" ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev912_linux_x86-64.tar.gz"
ARG MQ_PACKAGES="MQSeriesRuntime-*.rpm MQSeriesServer-*.rpm MQSeriesJava*.rpm MQSeriesJRE*.rpm MQSeriesGSKit*.rpm MQSeriesMsg*.rpm MQSeriesSamples*.rpm MQSeriesWeb*.rpm MQSeriesAMS-*.rpm" ARG MQ_PACKAGES="MQSeriesRuntime-*.rpm MQSeriesServer-*.rpm MQSeriesJava*.rpm MQSeriesJRE*.rpm MQSeriesGSKit*.rpm MQSeriesMsg*.rpm MQSeriesSamples*.rpm MQSeriesWeb*.rpm MQSeriesAMS-*.rpm"
#ARG MQ_PACKAGES="ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-web ibmmq-ams" #ARG MQ_PACKAGES="ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-web ibmmq-ams"
ARG MQM_UID=888 ARG MQM_UID=888
@@ -149,6 +147,6 @@ COPY incubating/mqadvanced-server-dev/web /etc/mqm/web
RUN chown -R mqm:mqm /etc/mqm/* \ RUN chown -R mqm:mqm /etc/mqm/* \
&& chmod +x /usr/local/bin/runmq* \ && chmod +x /usr/local/bin/runmq* \
&& install --directory --mode 0775 --owner mqm --group root /run/runmqdevserver && install --directory --mode 0775 --owner mqm --group root /run/runmqdevserver
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1 MQ_GENERATE_CERTIFICATE_HOSTNAME=localhost ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1
USER $MQM_UID USER $MQM_UID
ENTRYPOINT ["runmqdevserver"] ENTRYPOINT ["runmqdevserver"]

137
Makefile
View File

@@ -16,18 +16,10 @@
# Conditional variables - you can override the values of these variables from # Conditional variables - you can override the values of these variables from
# the command line # the command line
############################################################################### ###############################################################################
# RELEASE shows what release of the container code has been built
RELEASE ?=
# MQ_VERSION is the fully qualified MQ version number to build # MQ_VERSION is the fully qualified MQ version number to build
MQ_VERSION ?= 9.1.4.0 MQ_VERSION ?= 9.1.3.0
# MQ_ARCHIVE_REPOSITORY is a remote repository from which to pull the MQ_ARCHIVE (if required) # RELEASE shows what release of the container code has been built
MQ_ARCHIVE_REPOSITORY ?= RELEASE ?= 2
# MQ_ARCHIVE_REPOSITORY_DEV is a remote repository from which to pull the MQ_ARCHIVE_DEV (if required)
MQ_ARCHIVE_REPOSITORY_DEV ?=
# MQ_ARCHIVE_REPOSITORY_USER is the user for the remote repository (if required)
MQ_ARCHIVE_REPOSITORY_USER ?=
# MQ_ARCHIVE_REPOSITORY_CREDENTIAL is the password/API key for the remote repository (if required)
MQ_ARCHIVE_REPOSITORY_CREDENTIAL ?=
# MQ_ARCHIVE is the name of the file, under the downloads directory, from which MQ Advanced can # MQ_ARCHIVE is the name of the file, under the downloads directory, from which MQ Advanced can
# be installed. The default value is derived from MQ_VERSION, BASE_IMAGE and architecture # be installed. The default value is derived from MQ_VERSION, BASE_IMAGE and architecture
# Does not apply to MQ Advanced for Developers. # Does not apply to MQ Advanced for Developers.
@@ -51,20 +43,6 @@ MQ_PACKAGES ?=MQSeriesRuntime-*.rpm MQSeriesServer-*.rpm MQSeriesJava*.rpm MQSer
MQM_UID ?= 888 MQM_UID ?= 888
# COMMAND is the container command to run. "podman" or "docker" # COMMAND is the container command to run. "podman" or "docker"
COMMAND ?=$(shell type -p podman 2>&1 >/dev/null && echo podman || echo docker) COMMAND ?=$(shell type -p podman 2>&1 >/dev/null && echo podman || echo docker)
# MQ_DELIVERY_REGISTRY_HOSTNAME is a remote registry to push the MQ Image to (if required)
MQ_DELIVERY_REGISTRY_HOSTNAME ?=
# MQ_DELIVERY_REGISTRY_NAMESPACE is the namespace/path on the delivery registry (if required)
MQ_DELIVERY_REGISTRY_NAMESPACE ?=
# MQ_DELIVERY_REGISTRY_USER is the user for the remote registry (if required)
MQ_DELIVERY_REGISTRY_USER ?=
# MQ_DELIVERY_REGISTRY_CREDENTIAL is the password/API key for the remote registry (if required)
MQ_DELIVERY_REGISTRY_CREDENTIAL ?=
# REGISTRY_USER is the username used to login to the Red Hat registry
REGISTRY_USER ?=
# REGISTRY_PASS is the password used to login to the Red Hat registry
REGISTRY_PASS ?=
# ARCH is the platform architecture (e.g. amd64, ppc64le or s390x)
ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
############################################################################### ###############################################################################
# Other variables # Other variables
@@ -72,6 +50,8 @@ ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
GO_PKG_DIRS = ./cmd ./internal ./test GO_PKG_DIRS = ./cmd ./internal ./test
MQ_ARCHIVE_TYPE=LINUX MQ_ARCHIVE_TYPE=LINUX
MQ_ARCHIVE_DEV_PLATFORM=linux MQ_ARCHIVE_DEV_PLATFORM=linux
# ARCH is the platform architecture (e.g. amd64, ppc64le or s390x)
ARCH=$(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
# BUILD_SERVER_CONTAINER is the name of the web server container used at build time # BUILD_SERVER_CONTAINER is the name of the web server container used at build time
BUILD_SERVER_CONTAINER=build-server BUILD_SERVER_CONTAINER=build-server
# NUM_CPU is the number of CPUs available to Docker. Used to control how many # NUM_CPU is the number of CPUs available to Docker. Used to control how many
@@ -88,7 +68,7 @@ IMAGE_REVISION=$(shell git rev-parse HEAD)
IMAGE_SOURCE=$(shell git config --get remote.origin.url) IMAGE_SOURCE=$(shell git config --get remote.origin.url)
EMPTY:= EMPTY:=
SPACE:= $(EMPTY) $(EMPTY) SPACE:= $(EMPTY) $(EMPTY)
# MQ_VERSION_VRM is MQ_VERSION with only the Version, Release and Modifier fields (no Fix field). e.g. 9.1.4 instead of 9.1.4.0 # MQ_VERSION_VRM is MQ_VERSION with only the Version, Release and Modifier fields (no Fix field). e.g. 9.1.3 instead of 9.1.3.0
MQ_VERSION_VRM=$(subst $(SPACE),.,$(wordlist 1,3,$(subst .,$(SPACE),$(MQ_VERSION)))) MQ_VERSION_VRM=$(subst $(SPACE),.,$(wordlist 1,3,$(subst .,$(SPACE),$(MQ_VERSION))))
ifneq (,$(findstring Microsoft,$(shell uname -r))) ifneq (,$(findstring Microsoft,$(shell uname -r)))
@@ -115,28 +95,6 @@ MQ_ARCHIVE_DEV_9.1.0.0=mqadv_dev910_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).ta
MQ_ARCHIVE_DEV_9.1.1.0=mqadv_dev911_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz MQ_ARCHIVE_DEV_9.1.1.0=mqadv_dev911_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz
MQ_ARCHIVE_DEV_9.1.2.0=mqadv_dev912_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz MQ_ARCHIVE_DEV_9.1.2.0=mqadv_dev912_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz
MQ_ARCHIVE_DEV_9.1.3.0=mqadv_dev913_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz MQ_ARCHIVE_DEV_9.1.3.0=mqadv_dev913_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz
MQ_ARCHIVE_DEV_9.1.4.0=mqadv_dev914_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz
ifneq "$(MQ_DELIVERY_REGISTRY_NAMESPACE)" "$(EMPTY)"
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)/$(MQ_DELIVERY_REGISTRY_NAMESPACE)
else
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)
endif
ifneq "$(RELEASE)" "$(EMPTY)"
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server
MQ_IMAGE_DEVSERVER=ibm-mqadvanced-server-dev
MQ_TAG=$(MQ_VERSION)-$(RELEASE)-$(ARCH)
EXTRA_LABELS=--label release=$(RELEASE)
endif
MQ_IMAGE_FULL_RELEASE_NAME=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
MQ_IMAGE_DEV_FULL_RELEASE_NAME=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG)
ifeq "$(MQ_DELIVERY_REGISTRY_HOSTNAME)" "ibmcom"
MQ_IMAGE_DEVSERVER_DOCKERHUB=mq
else ifeq "$(MQ_DELIVERY_REGISTRY_HOSTNAME)" "ibmcorp"
MQ_IMAGE_DEVSERVER_DOCKERHUB=mqadvanced-server-dev
endif
############################################################################### ###############################################################################
# Build targets # Build targets
@@ -161,18 +119,12 @@ incubating: build-explorer
downloads/$(MQ_ARCHIVE_DEV): downloads/$(MQ_ARCHIVE_DEV):
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END))) $(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
mkdir -p downloads mkdir -p downloads
ifneq "$(MQ_ARCHIVE_REPOSITORY_DEV)" "$(EMPTY)" cd downloads; curl -LO https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_ARCHIVE_DEV)
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY_DEV)" -o downloads/$(MQ_ARCHIVE_DEV)
else
curl -L https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_ARCHIVE_DEV) -o downloads/$(MQ_ARCHIVE_DEV)
endif
downloads/$(MQ_ARCHIVE): downloads/$(MQ_SDK_ARCHIVE):
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced "$(MQ_VERSION)$(END))) $(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
mkdir -p downloads mkdir -p downloads
ifneq "$(MQ_ARCHIVE_REPOSITORY)" "$(EMPTY)" cd downloads; curl -LO https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_SDK_ARCHIVE)
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY)" -o downloads/$(MQ_ARCHIVE)
endif
.PHONY: downloads .PHONY: downloads
downloads: downloads/$(MQ_ARCHIVE_DEV) downloads/$(MQ_SDK_ARCHIVE) downloads: downloads/$(MQ_ARCHIVE_DEV) downloads/$(MQ_SDK_ARCHIVE)
@@ -248,12 +200,12 @@ define build-mq
--label version=$(MQ_VERSION) \ --label version=$(MQ_VERSION) \
--label name=$1 \ --label name=$1 \
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \ --label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
--label release="$(RELEASE)" \
--label architecture="$(ARCH)" \ --label architecture="$(ARCH)" \
--label run="docker run -d -e LICENSE=accept $1:$2" \ --label run="docker run -d -e LICENSE=accept $1:$2" \
--label vcs-ref=$(IMAGE_REVISION) \ --label vcs-ref=$(IMAGE_REVISION) \
--label vcs-type=git \ --label vcs-type=git \
--label vcs-url=$(IMAGE_SOURCE) \ --label vcs-url=$(IMAGE_SOURCE) \
$(EXTRA_LABELS) \
--target $5 \ --target $5 \
. .
$(if $(findstring docker,$(COMMAND)), @docker kill $(BUILD_SERVER_CONTAINER)) $(if $(findstring docker,$(COMMAND)), @docker kill $(BUILD_SERVER_CONTAINER))
@@ -278,7 +230,7 @@ endif
build-advancedserver-host: build-advancedserver build-advancedserver-host: build-advancedserver
.PHONY: build-advancedserver .PHONY: build-advancedserver
build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) command-version build-advancedserver: log-build-env downloads/$(MQ_ARCHIVE) command-version
$(info $(SPACER)$(shell printf $(TITLE)"Build $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)"$(END))) $(info $(SPACER)$(shell printf $(TITLE)"Build $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)"$(END)))
$(call build-mq,$(MQ_IMAGE_ADVANCEDSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE),mq-server) $(call build-mq,$(MQ_IMAGE_ADVANCEDSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE),mq-server)
@@ -286,41 +238,33 @@ build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) comma
build-devserver-host: build-devserver build-devserver-host: build-devserver
.PHONY: build-devserver .PHONY: build-devserver
build-devserver: registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version build-devserver: log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)"$(END))) $(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)"$(END)))
$(call build-mq,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE_DEV),mq-dev-server) $(call build-mq,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE_DEV),mq-dev-server)
.PHONY: build-advancedserver-cover .PHONY: build-advancedserver-cover
build-advancedserver-cover: registry-login command-version build-advancedserver-cover: command-version
$(COMMAND) build --build-arg BASE_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) -t $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)-cover -f Dockerfile-server.cover . $(COMMAND) build --build-arg BASE_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) -t $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)-cover -f Dockerfile-server.cover .
.PHONY: build-explorer .PHONY: build-explorer
build-explorer: registry-login downloads/$(MQ_ARCHIVE_DEV) build-explorer: downloads/$(MQ_ARCHIVE_DEV)
$(call build-mq,mq-explorer,latest-$(ARCH),incubating/mq-explorer/Dockerfile,$(MQ_ARCHIVE_DEV),mq-explorer) $(call build-mq,mq-explorer,latest-$(ARCH),incubating/mq-explorer/Dockerfile,$(MQ_ARCHIVE_DEV),mq-explorer)
.PHONY: build-sdk .PHONY: build-sdk
build-sdk: registry-login downloads/$(MQ_ARCHIVE_DEV) build-sdk: downloads/$(MQ_ARCHIVE_DEV)
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_SDK)"$(END))) $(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_SDK)"$(END)))
$(call build-mq,mq-sdk,$(MQ_TAG),incubating/mq-sdk/Dockerfile,$(MQ_SDK_ARCHIVE),mq-sdk) $(call build-mq,mq-sdk,$(MQ_TAG),incubating/mq-sdk/Dockerfile,$(MQ_SDK_ARCHIVE),mq-sdk)
.PHONY: registry-login
registry-login:
ifneq ($(REGISTRY_USER),)
$(COMMAND) login -u $(REGISTRY_USER) -p $(REGISTRY_PASS) registry.redhat.io
endif
.PHONY: log-build-env .PHONY: log-build-env
log-build-vars: log-build-vars:
$(info $(SPACER)$(shell printf $(TITLE)"Build environment"$(END))) $(info $(SPACER)$(shell printf $(TITLE)"Build environment"$(END)))
@echo ARCH=$(ARCH) @echo ARCH=$(ARCH)
@echo MQ_VERSION=$(MQ_VERSION) @echo MQ_VERSION=$(MQ_VERSION)
@echo MQ_ARCHIVE=$(MQ_ARCHIVE) @echo MQ_ARCHIVE=$(MQ_ARCHIVE)
@echo MQ_ARCHIVE_DEV=$(MQ_ARCHIVE_DEV)
@echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER) @echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER)
@echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER) @echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER)
@echo COMMAND=$(COMMAND) @echo COMMAND=$(COMMAND)
@echo MQM_UID=$(MQM_UID) @echo MQM_UID=$(MQM_UID)
@echo REGISTRY_USER=$(REGISTRY_USER)
.PHONY: log-build-env .PHONY: log-build-env
log-build-env: log-build-vars log-build-env: log-build-vars
@@ -330,58 +274,15 @@ log-build-env: log-build-vars
include formatting.mk include formatting.mk
.PHONY: pull-mq-archive
pull-mq-archive:
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY)" -o downloads/$(MQ_ARCHIVE)
.PHONY: pull-mq-archive-dev
pull-mq-archive-dev:
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY_DEV)" -o downloads/$(MQ_ARCHIVE_DEV)
.PHONY: push-advancedserver
push-advancedserver:
$(info $(SPACER)$(shell printf $(TITLE)"Push production image to $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) tag $(MQ_IMAGE_ADVANCEDSERVER)\:$(MQ_TAG) $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_FULL_RELEASE_NAME)
$(COMMAND) push $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_FULL_RELEASE_NAME)
.PHONY: push-devserver
push-devserver:
$(info $(SPACER)$(shell printf $(TITLE)"Push developer image to $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) tag $(MQ_IMAGE_DEVSERVER)\:$(MQ_TAG) $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME)
$(COMMAND) push $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME)
.PHONY: push-devserver-dockerhub
push-devserver-dockerhub:
$(info $(SPACER)$(shell printf $(TITLE)"Push developer image to $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) tag $(MQ_IMAGE_DEVSERVER)\:$(MQ_TAG) $(MQ_DELIVERY_REGISTRY_HOSTNAME)/$(MQ_IMAGE_DEVSERVER_DOCKERHUB):$(MQ_TAG)
$(COMMAND) push $(MQ_DELIVERY_REGISTRY_HOSTNAME)/$(MQ_IMAGE_DEVSERVER_DOCKERHUB):$(MQ_TAG)
.PHONY: pull-advancedserver
pull-advancedserver:
$(info $(SPACER)$(shell printf $(TITLE)"Pull production image from $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) pull $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_FULL_RELEASE_NAME)
$(COMMAND) tag $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_FULL_RELEASE_NAME) $(MQ_IMAGE_ADVANCEDSERVER)\:$(MQ_TAG)
.PHONY: pull-devserver
pull-devserver:
$(info $(SPACER)$(shell printf $(TITLE)"Pull developer image from $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) pull $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME)
$(COMMAND) tag $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME) $(MQ_IMAGE_DEVSERVER)\:$(MQ_TAG)
.PHONY: clean .PHONY: clean
clean: clean:
rm -rf ./coverage rm -rf ./coverage
rm -rf ./build rm -rf ./build
rm -rf ./deps rm -rf ./deps
.PHONY: install-build-deps .PHONY: deps
install-build-deps: deps:
ARCH=$(ARCH) ./install-build-deps.sh glide install --strip-vendor
.PHONY: build-cov .PHONY: build-cov
build-cov: build-cov:

View File

@@ -45,7 +45,8 @@ The Dockerfiles and associated code and scripts are licensed under the [Apache L
Licenses for the products installed within the images are as follows: Licenses for the products installed within the images are as follows:
- [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BBZHCQ) (International License Agreement for Non-Warranted Programs). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above. - [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BBZHCQ) (International License Agreement for Non-Warranted Programs). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
- [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BGMHFW) (International Program License Agreement). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above. - [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BBSHJL) (International Program License Agreement). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
- License information for Ubuntu packages may be found in `/usr/share/doc/${package}/copyright`
Note: The IBM MQ Advanced for Developers license does not permit further distribution and the terms restrict usage to a developer machine. Note: The IBM MQ Advanced for Developers license does not permit further distribution and the terms restrict usage to a developer machine.

View File

@@ -23,7 +23,7 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/ibm-messaging/mq-container/pkg/name" "github.com/ibm-messaging/mq-container/internal/name"
) )
func queueManagerHealthy() (bool, error) { func queueManagerHealthy() (bool, error) {

View File

@@ -22,8 +22,8 @@ import (
"net" "net"
"os" "os"
"github.com/ibm-messaging/mq-container/internal/name"
"github.com/ibm-messaging/mq-container/internal/ready" "github.com/ibm-messaging/mq-container/internal/ready"
"github.com/ibm-messaging/mq-container/pkg/name"
) )
func main() { func main() {

View File

@@ -22,10 +22,11 @@ import (
"os/exec" "os/exec"
"syscall" "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/mqtemplate"
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger" "github.com/ibm-messaging/mq-container/internal/name"
"github.com/ibm-messaging/mq-container/pkg/logger"
"github.com/ibm-messaging/mq-container/pkg/name"
) )
var log *logger.Logger var log *logger.Logger
@@ -42,7 +43,7 @@ func setPassword(user string, password string) error {
if err != nil { if err != nil {
log.Errorf("Error closing password stdin: %v", err) log.Errorf("Error closing password stdin: %v", err)
} }
out, err := cmd.CombinedOutput() out, _, err := command.RunCmd(cmd)
if err != nil { if err != nil {
// Include the command output in the error // Include the command output in the error
return fmt.Errorf("%v: %v", err.Error(), out) return fmt.Errorf("%v: %v", err.Error(), out)
@@ -171,7 +172,7 @@ func main() {
} else { } else {
// Replace this process with runmqserver // Replace this process with runmqserver
// #nosec G204 // #nosec G204
err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-nologruntime", "-dev"}, os.Environ()) err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-dev"}, os.Environ())
if err != nil { if err != nil {
log.Errorf("Error replacing this process with runmqserver: %v", err) log.Errorf("Error replacing this process with runmqserver: %v", err)
} }

View File

@@ -27,8 +27,8 @@ import (
"sync" "sync"
"github.com/ibm-messaging/mq-container/internal/command" "github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
"github.com/ibm-messaging/mq-container/pkg/mqini" "github.com/ibm-messaging/mq-container/internal/mqini"
) )
// var debug = false // var debug = false

View File

@@ -24,19 +24,18 @@ import (
"os" "os"
"sync" "sync"
"github.com/ibm-messaging/mq-container/internal/containerruntimelogger"
"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/name"
"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/internal/mqini"
"github.com/ibm-messaging/mq-container/pkg/name"
) )
func doMain() error { func doMain() error {
var initFlag = flag.Bool("i", false, "initialize volume only, then exit") var initFlag = flag.Bool("i", false, "initialize volume only, then exit")
var infoFlag = flag.Bool("info", false, "Display debug info, then exit") var infoFlag = flag.Bool("info", false, "Display debug info, then exit")
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 log output")
var devFlag = flag.Bool("dev", false, "used when running this program from runmqdevserver to control how TLS is configured")
flag.Parse() flag.Parse()
name, nameErr := name.GetQueueManagerName() name, nameErr := name.GetQueueManagerName()
@@ -89,7 +88,7 @@ func doMain() error {
// Enable diagnostic collecting on failure // Enable diagnostic collecting on failure
collectDiagOnFail = true collectDiagOnFail = true
if *noLogRuntimeFlag == false { if *devFlag == false {
err = containerruntimelogger.LogContainerDetails(log) err = containerruntimelogger.LogContainerDetails(log)
if err != nil { if err != nil {
logTermination(err) logTermination(err)
@@ -177,7 +176,7 @@ func doMain() error {
return err return err
} }
err = mqinimerge.AddStanzas(name) err = mqini.AddStanzas(name)
if err != nil { if err != nil {
logTermination(err) logTermination(err)
return err return err

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2017, 2019 © Copyright IBM Corporation 2017, 2018
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
) )
var test *bool var test *bool

View File

@@ -30,15 +30,10 @@ func postInit(name, keylabel string, p12Trust tls.KeyStoreData) error {
if err != nil { if err != nil {
return err return err
} }
// If trust-store is empty, set reference to point to the key-store
p12TrustStoreRef := "MQWebTrustStore"
if len(p12Trust.TrustedCerts) == 0 {
p12TrustStoreRef = "MQWebKeyStore"
}
// Start the web server, in the background (if installed) // Start the web server, in the background (if installed)
// WARNING: No error handling or health checking available for the web server // WARNING: No error handling or health checking available for the web server
go func() { go func() {
err = startWebServer(keystore, p12Trust.Password, p12TrustStoreRef) err = startWebServer(keystore, p12Trust.Password)
if err != nil { if err != nil {
log.Printf("Error starting web server: %v", err) log.Printf("Error starting web server: %v", err)
} }

View File

@@ -175,7 +175,7 @@ func stopQueueManager(name string) error {
log.Println("Stopping queue manager") log.Println("Stopping queue manager")
isStandby, err := ready.IsRunningAsStandbyQM(name) isStandby, err := ready.IsRunningAsStandbyQM(name)
if err != nil { if err != nil {
log.Printf("Error getting status for queue manager %v: %v", name, err.Error()) log.Printf("Error getting status for queue manager %v: ", name, err.Error())
return err return err
} }
args := []string{"-w", "-r", name} args := []string{"-w", "-r", name}

View File

@@ -118,11 +118,11 @@ func configureTLS(certLabel string, cmsKeystore tls.KeyStoreData, devmode bool)
return nil return nil
} }
// configureWebKeyStore configures the key stores for the web console // configureSSOTLS configures MQ Console TLS for Single Sign-On
func configureWebKeyStore(p12TrustStore tls.KeyStoreData) (string, error) { func configureSSOTLS(p12TrustStore tls.KeyStoreData) (string, error) {
// TODO find way to supply this // TODO find way to supply this
// Override the webstore variables to hard coded defaults // Override the webstore variables to hard coded defaults
webKeyStoreName := tls.WebDefaultLabel + ".p12" webKeyStoreName := tls.IntegrationDefaultLabel + ".p12"
// Check keystore exists // Check keystore exists
ks := filepath.Join(keyStoreDir, webKeyStoreName) ks := filepath.Join(keyStoreDir, webKeyStoreName)

View File

@@ -31,7 +31,7 @@ import (
"github.com/ibm-messaging/mq-container/internal/tls" "github.com/ibm-messaging/mq-container/internal/tls"
) )
func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error { func startWebServer(keystore, keystorepw string) error {
_, err := os.Stat("/opt/mqm/bin/strmqweb") _, err := os.Stat("/opt/mqm/bin/strmqweb")
if err != nil && os.IsNotExist(err) { if err != nil && os.IsNotExist(err) {
log.Debug("Skipping web server, because it's not installed") log.Debug("Skipping web server, because it's not installed")
@@ -53,7 +53,6 @@ func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error {
if keystore != "" { if keystore != "" {
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+keystore) cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+keystore)
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+keystorepw) cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+keystorepw)
cmd.Env = append(cmd.Env, "AMQ_WEBTRUSTSTOREREF="+p12TrustStoreRef)
} }
uid, gid, err := command.LookupMQM() uid, gid, err := command.LookupMQM()
@@ -73,8 +72,7 @@ func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error {
cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)} cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
} }
out, err := cmd.CombinedOutput() out, rc, err := command.RunCmd(cmd)
rc := cmd.ProcessState.ExitCode()
if err != nil { if err != nil {
log.Printf("Error %v starting web server: %v", rc, string(out)) log.Printf("Error %v starting web server: %v", rc, string(out))
return err return err
@@ -119,12 +117,11 @@ func configureSSO(p12TrustStore tls.KeyStoreData) (string, error) {
} }
// Configure SSO TLS // Configure SSO TLS
return configureWebKeyStore(p12TrustStore) return configureSSOTLS(p12TrustStore)
} }
func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, error) { func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, error) {
var keystore string var keystore string
// Configure TLS for Web Console first if we have a certificate to use // Configure TLS for Web Console first if we have a certificate to use
err := configureWebTLS(keyLabel) err := configureWebTLS(keyLabel)
if err != nil { if err != nil {
@@ -141,10 +138,7 @@ func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, err
if err != nil { if err != nil {
return keystore, err return keystore, err
} }
} else if keyLabel == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") != "" {
keystore, err = configureWebKeyStore(p12Trust)
} }
_, err = os.Stat("/opt/mqm/bin/strmqweb") _, err = os.Stat("/opt/mqm/bin/strmqweb")
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {

View File

@@ -9,16 +9,13 @@ You need to have the following tools installed:
If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first. If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first.
You will also need a [Red Hat Account](https://access.redhat.com) to be able to access the Red Hat Registry.
## Building a production image ## Building a production image
This procedure works for building the MQ Continuous Delivery release, on `amd64`, `ppc64le` and `s390x` architectures. This procedure works for building the MQ Continuous Delivery release, on `amd64`, `ppc64le` and `s390x` architectures.
1. Create a `downloads` directory in the root of this repository 1. Create a `downloads` directory in the root of this repository
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `IBM_MQ_9.1.4_LINUX_X86-64.tar.gz`) in the `downloads` directory 2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `IBM_MQ_9.1.3_LINUX_X86-64.tar.gz`) in the `downloads` directory
3. Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials. 3. Run `make build-advancedserver`
4. Run `make build-advancedserver`
> **Warning**: Note that MQ offers two different sets of packaging on Linux: one is called "MQ for Linux" and contains RPM files for installing on Red Hat Enterprise Linux and SUSE Linux Enterprise Server; the other is for Ubuntu. The MQ container build uses a Red Hat Universal Base Image, so you need the "MQ for Linux" RPM files. > **Warning**: Note that MQ offers two different sets of packaging on Linux: one is called "MQ for Linux" and contains RPM files for installing on Red Hat Enterprise Linux and SUSE Linux Enterprise Server; the other is for Ubuntu. The MQ container build uses a Red Hat Universal Base Image, so you need the "MQ for Linux" RPM files.
@@ -29,8 +26,6 @@ MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
``` ```
## Building a developer image ## Building a developer image
Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
Run `make build-devserver`, which will download the latest version of MQ Advanced for Developers from IBM developerWorks. This is currently only available on the `amd64` architecture. Run `make build-devserver`, which will download the latest version of MQ Advanced for Developers from IBM developerWorks. This is currently only available on the `amd64` architecture.
You can use the environment variable `MQ_ARCHIVE_DEV` to specify an alternative local file to install from (which must be in the `downloads` directory). You can use the environment variable `MQ_ARCHIVE_DEV` to specify an alternative local file to install from (which must be in the `downloads` directory).

View File

@@ -34,6 +34,11 @@ Two channels are created, one for administration, the other for normal messaging
* DEV.ADMIN.SVRCONN - configured to only allow the `admin` user to connect into it. A user and password must be supplied. * DEV.ADMIN.SVRCONN - configured to only allow the `admin` user to connect into it. A user and password must be supplied.
* DEV.APP.SVRCONN - does not allow administrative users to connect. Password is optional unless you choose a password for app users. * DEV.APP.SVRCONN - does not allow administrative users to connect. Password is optional unless you choose a password for app users.
A new listener is created (the SYSTEM listener is fine, but system objects are not shown by default in the web console):
* DEV.LISTENER.TCP - listens on port 1414.
## Web Console ## Web Console
By default the MQ Advanced for Developers image will start the IBM MQ Web Console that allows you to administer your Queue Manager running on your container. When the web console has been started, you can access it by opening a web browser and navigating to https://<Container IP>:9443/ibmmq/console. Where <Container IP> is replaced by the IP address of your running container. By default the MQ Advanced for Developers image will start the IBM MQ Web Console that allows you to administer your Queue Manager running on your container. When the web console has been started, you can access it by opening a web browser and navigating to https://<Container IP>:9443/ibmmq/console. Where <Container IP> is replaced by the IP address of your running container.

View File

@@ -16,7 +16,7 @@ docker run \
--env LICENSE=accept \ --env LICENSE=accept \
--env MQ_QMGR_NAME=QM1 \ --env MQ_QMGR_NAME=QM1 \
--detach \ --detach \
mqadvanced-server:9.1.4.0-amd64 mqadvanced-server:9.1.3.0-amd64
``` ```
The MQ Advanced for Developers image does require the "chown", "setuid", "setgid" and "audit_write" capabilities (plus "dac_override" if you're using an image based on Red Hat Enterprise Linux). This is because it uses the "sudo" command to change passwords inside the container. For example, in Docker, you could do the following: The MQ Advanced for Developers image does require the "chown", "setuid", "setgid" and "audit_write" capabilities (plus "dac_override" if you're using an image based on Red Hat Enterprise Linux). This is because it uses the "sudo" command to change passwords inside the container. For example, in Docker, you could do the following:
@@ -31,7 +31,7 @@ docker run \
--env LICENSE=accept \ --env LICENSE=accept \
--env MQ_QMGR_NAME=QM1 \ --env MQ_QMGR_NAME=QM1 \
--detach \ --detach \
mqadvanced-server-dev:9.1.4.0-amd64 mqadvanced-server-dev:9.1.3.0-amd64
``` ```
### SELinux ### SELinux

View File

@@ -24,7 +24,7 @@ make test-advancedserver
You can specify the image to use directly by using the `MQ_IMAGE_ADVANCEDSERVER` or `MQ_IMAGE_DEVSERVER` variables, for example: You can specify the image to use directly by using the `MQ_IMAGE_ADVANCEDSERVER` or `MQ_IMAGE_DEVSERVER` variables, for example:
``` ```
MQ_IMAGE_ADVANCEDSERVER=mqadvanced-server:9.1.4.0-amd64 make test-advancedserver MQ_IMAGE_ADVANCEDSERVER=mqadvanced-server:9.1.3.0-amd64 make test-advancedserver
``` ```
You can pass parameters to `go test` with an environment variable. For example, to run the "TestGoldenPath" test, run the following command:: You can pass parameters to `go test` with an environment variable. For example, to run the "TestGoldenPath" test, run the following command::
@@ -33,10 +33,10 @@ You can pass parameters to `go test` with an environment variable. For example,
TEST_OPTS_DOCKER="-run TestGoldenPath" make test-advancedserver TEST_OPTS_DOCKER="-run TestGoldenPath" make test-advancedserver
``` ```
You can also use the same environment variables you specified when [building](./building), for example, the following will try and test an image called `mqadvanced-server:9.1.4.0-amd64`: You can also use the same environment variables you specified when [building](./building), for example, the following will try and test an image called `mqadvanced-server:9.1.3.0-amd64`:
``` ```
MQ_VERSION=9.1.4.0 make test-advancedserver MQ_VERSION=9.1.3.0 make test-advancedserver
``` ```
### Running the Docker tests with code coverage ### Running the Docker tests with code coverage

57
glide.lock generated Normal file
View File

@@ -0,0 +1,57 @@
hash: 6ebd5fb1c39729378c7256da6f312e9699bff1ddff9941d3c8c1ba785e22acfd
updated: 2019-05-21T10:38:01.227081+01:00
imports:
- name: github.com/beorn7/perks
version: 3a771d992973f24aa725d07868b467d1ddfceafb
subpackages:
- quantile
- name: github.com/genuinetools/amicontained
version: fcae88544f0212fbb1e20699c41566655b68679b
subpackages:
- container
- name: github.com/golang/protobuf
version: 70b3af33377e7aa25ae42977bed93cc6b90f0373
subpackages:
- proto
- name: github.com/ibm-messaging/mq-golang
version: 1b2a2ad95ba3c555944be28097d392c27bda4071
subpackages:
- ibmmq
- mqmetric
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
- name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317
subpackages:
- prometheus
- name: github.com/prometheus/client_model
version: 5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f
subpackages:
- go
- name: github.com/prometheus/common
version: 7600349dcfe1abd18d72d3a1770870d9800a7801
subpackages:
- expfmt
- internal/bitbucket.org/ww/goautoneg
- model
- name: github.com/prometheus/procfs
version: ae68e2d4c00fed4943b5f6698d504a5fe083da8a
subpackages:
- internal/util
- nfs
- xfs
- name: github.com/syndtr/gocapability
version: 33e07d32887e1e06b7c025f27ce52f62c7990bc0
subpackages:
- capability
- name: golang.org/x/sys
version: 1b2967e3c290b7c545b3db0deeda16e9be4f98a2
subpackages:
- unix
- name: software.sslmate.com/src/go-pkcs12
version: 6e380ad96778cc63c6ea17649a9b74224bceafe9
subpackages:
- internal/rc2
testImports: []

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2019 # © Copyright IBM Corporation 2017, 2019
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -12,17 +12,19 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
image: ibmcom/mq:9.1.4.0-r1 package: github.com/ibm-messaging/mq-container
manifests: license: Apache-2.0
- image: ibmcom/mq:9.1.4.0-r1-amd64 excludeDirs:
platform: - build
architecture: amd64 - coverage
os: linux - test
- image: ibmcom/mq:9.1.4.0-r1-ppc64le import:
platform: - package: golang.org/x/sys/unix
architecture: ppc64le - package: github.com/prometheus/client_golang
os: linux version: 0.8.0
- image: ibmcom/mq:9.1.4.0-r1-s390x - package: github.com/ibm-messaging/mq-golang
platform: version: 2.0.0
architecture: s390x - package: github.com/genuinetools/amicontained
os: linux version: 0.4.0
- package: software.sslmate.com/src/go-pkcs12
commit: 6e380ad96778cc63c6ea17649a9b74224bceafe9

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
FROM registry.redhat.io/ubi8/ubi-minimal AS mq-explorer FROM registry.access.redhat.com/ubi7/ubi-minimal AS mq-explorer
# The URL to download the MQ installer from in tar.gz format # The URL to download the MQ installer from in tar.gz format
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev912_linux_x86-64.tar.gz" ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev912_linux_x86-64.tar.gz"
@@ -22,7 +22,7 @@ ENV MQ_PACKAGES="MQSeriesRuntime*.rpm MQSeriesJRE*.rpm MQSeriesExplorer*.rpm"
ARG MQM_UID=888 ARG MQM_UID=888
RUN microdnf install -y gtk2 libXtst \ RUN microdnf install -y --nodocs gtk2 libXtst \
&& microdnf clean all && microdnf clean all
ADD install-mq.sh /usr/local/bin/ ADD install-mq.sh /usr/local/bin/

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
FROM registry.redhat.io/rhel8/llvm-toolset:8.0.1-10 AS mq-sdk FROM registry.access.redhat.com/rhscl/devtoolset-7-toolchain-rhel7 AS mq-sdk
#FROM docker.io/centos/devtoolset-7-toolchain-centos7 AS mq-sdk #FROM docker.io/centos/devtoolset-7-toolchain-centos7 AS mq-sdk
# The URL to download the MQ installer from in tar.gz format # The URL to download the MQ installer from in tar.gz format

View File

@@ -13,6 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
STOP LISTENER('SYSTEM.LISTENER.TCP.1') IGNSTATE(YES)
ALTER LISTENER('SYSTEM.LISTENER.TCP.1') TRPTYPE(TCP) CONTROL(MANUAL)
* Developer queues * Developer queues
DEFINE QLOCAL('DEV.QUEUE.1') REPLACE DEFINE QLOCAL('DEV.QUEUE.1') REPLACE
DEFINE QLOCAL('DEV.QUEUE.2') REPLACE DEFINE QLOCAL('DEV.QUEUE.2') REPLACE
@@ -45,3 +48,7 @@ SET CHLAUTH('DEV.ADMIN.SVRCONN') TYPE(USERMAP) CLNTUSER('admin') USERSRC(CHANNEL
SET AUTHREC GROUP('mqclient') OBJTYPE(QMGR) AUTHADD(CONNECT,INQ) SET AUTHREC GROUP('mqclient') OBJTYPE(QMGR) AUTHADD(CONNECT,INQ)
SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(QUEUE) AUTHADD(BROWSE,GET,INQ,PUT) SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(QUEUE) AUTHADD(BROWSE,GET,INQ,PUT)
SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(TOPIC) AUTHADD(PUB,SUB) SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(TOPIC) AUTHADD(PUB,SUB)
* Developer listener
DEFINE LISTENER('DEV.LISTENER.TCP') TRPTYPE(TCP) PORT(1414) CONTROL(QMGR) REPLACE
START LISTENER('DEV.LISTENER.TCP') IGNSTATE(YES)

View File

@@ -15,9 +15,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# Fail on any non-zero return code
set -ex
test -f /usr/bin/yum && YUM=true || YUM=false test -f /usr/bin/yum && YUM=true || YUM=false
test -f /usr/bin/microdnf && MICRODNF=true || MICRODNF=false test -f /usr/bin/microdnf && MICRODNF=true || MICRODNF=false
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
@@ -36,6 +33,6 @@ if ($YUM); then
fi fi
if ($MICRODNF); then if ($MICRODNF); then
microdnf install sudo microdnf install --nodocs sudo
microdnf clean all microdnf clean all
fi fi

View File

@@ -19,8 +19,8 @@
set -ex set -ex
sudo curl -Lo /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.5.1/dep-linux-$ARCH curl https://glide.sh/get | sh
sudo curl -Lo /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64
sudo chmod +x /usr/local/bin/dep sudo chmod +x /usr/local/bin/dep
go get -u golang.org/x/lint/golint go get -u golang.org/x/lint/golint
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $GOPATH/bin 2.0.0 || echo "Gosec not installed. Platform may not be supported."

View File

@@ -63,10 +63,10 @@ if ($UBUNTU); then
fi fi
if ($RPM); then if ($RPM); then
EXTRA_RPMS="bash bc ca-certificates file findutils gawk glibc-common grep passwd procps-ng sed shadow-utils tar util-linux which" EXTRA_RPMS="bash bc ca-certificates coreutils file findutils gawk glibc-common grep passwd procps-ng sed shadow-utils tar util-linux which"
# Install additional packages required by MQ, this install process and the runtime scripts # Install additional packages required by MQ, this install process and the runtime scripts
$YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS} $YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS}
$MICRODNF && microdnf install ${EXTRA_RPMS} $MICRODNF && microdnf install --nodocs ${EXTRA_RPMS}
fi fi
# Apply any bug fixes not included in base Ubuntu or MQ image. # Apply any bug fixes not included in base Ubuntu or MQ image.

View File

@@ -94,7 +94,7 @@ ln -s /mnt/mqm/data /var/mqm
sed -i 's/PASS_MAX_DAYS\t99999/PASS_MAX_DAYS\t90/' /etc/login.defs sed -i 's/PASS_MAX_DAYS\t99999/PASS_MAX_DAYS\t90/' /etc/login.defs
sed -i 's/PASS_MIN_DAYS\t0/PASS_MIN_DAYS\t1/' /etc/login.defs sed -i 's/PASS_MIN_DAYS\t0/PASS_MIN_DAYS\t1/' /etc/login.defs
sed -i 's/PASS_MIN_LEN\t5/PASS_MIN_LEN\t8/' /etc/login.defs sed -i 's/PASS_MIN_LEN\t5/PASS_MIN_LEN\t8/' /etc/login.defs
$RPM && sed -i 's/# minlen/minlen/' /etc/security/pwquality.conf sed -i 's/# minlen = 9/minlen = 8/' /etc/security/pwquality.conf
$UBUNTU && PAM_FILE=/etc/pam.d/common-password $UBUNTU && PAM_FILE=/etc/pam.d/common-password
$RPM && PAM_FILE=/etc/pam.d/password-auth $RPM && PAM_FILE=/etc/pam.d/password-auth
@@ -104,10 +104,6 @@ sed -i 's/password\t\[success=1 default=ignore\]\tpam_unix\.so obscure sha512/pa
$RPM && rpm -q --all || true $RPM && rpm -q --all || true
$UBUNTU && dpkg --list || true $UBUNTU && dpkg --list || true
#Update the license file to include UBI 8 instead of UBI 7
sed -i 's/v7.0/v8.0/g' /opt/mqm/licenses/non_ibm_license.txt
# Copy MQ Licenses into the correct location # Copy MQ Licenses into the correct location
mkdir -p /licenses mkdir -p /licenses
cp /opt/mqm/licenses/*.txt /licenses/ cp /opt/mqm/licenses/*.txt /licenses/

View File

@@ -21,24 +21,40 @@ import (
"fmt" "fmt"
"os/exec" "os/exec"
"os/user" "os/user"
"runtime"
"strconv" "strconv"
"syscall" "syscall"
) )
// RunCmd runs an OS command. On Linux it waits for the command to
// complete and returns the exit status (return code).
// Do not use this function to run shell built-ins (like "cd"), because
// the error handling works differently
func RunCmd(cmd *exec.Cmd) (string, int, error) {
// Run the command and wait for completion
out, err := cmd.CombinedOutput()
if err != nil {
// Assert that this is an ExitError
exiterr, ok := err.(*exec.ExitError)
// If the type assertion was correct, and we're on Linux
if ok && runtime.GOOS == "linux" {
status, ok := exiterr.Sys().(syscall.WaitStatus)
if ok {
return string(out), status.ExitStatus(), fmt.Errorf("%v: %v", cmd.Path, err)
}
}
return string(out), -1, err
}
return string(out), 0, nil
}
// Run runs an OS command. On Linux it waits for the command to // Run runs an OS command. On Linux it waits for the command to
// complete and returns the exit status (return code). // complete and returns the exit status (return code).
// Do not use this function to run shell built-ins (like "cd"), because // Do not use this function to run shell built-ins (like "cd"), because
// the error handling works differently // the error handling works differently
func Run(name string, arg ...string) (string, int, error) { func Run(name string, arg ...string) (string, int, error) {
// Run the command and wait for completion
// #nosec G204 // #nosec G204
cmd := exec.Command(name, arg...) return RunCmd(exec.Command(name, arg...))
out, err := cmd.CombinedOutput()
rc := cmd.ProcessState.ExitCode()
if err != nil {
return string(out), rc, fmt.Errorf("%v: %v", cmd.Path, err)
}
return string(out), rc, nil
} }
// RunAsMQM runs the specified command as the mqm user // RunAsMQM runs the specified command as the mqm user
@@ -51,7 +67,7 @@ func RunAsMQM(name string, arg ...string) (string, int, error) {
return "", 0, err return "", 0, err
} }
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)} cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
return Run(name, arg...) return RunCmd(cmd)
} }
// LookupMQM looks up the UID & GID of the mqm user // LookupMQM looks up the UID & GID of the mqm user

View File

@@ -22,8 +22,8 @@ import (
"strings" "strings"
"github.com/ibm-messaging/mq-container/internal/containerruntime" "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/internal/user"
"github.com/ibm-messaging/mq-container/pkg/logger"
) )
// LogContainerDetails logs details about the container runtime // LogContainerDetails logs details about the container runtime

View File

@@ -152,7 +152,7 @@ func (ks *KeyStore) Import(inputFile, password string) error {
// CreateSelfSignedCertificate creates a self-signed certificate in the keystore // CreateSelfSignedCertificate creates a self-signed certificate in the keystore
func (ks *KeyStore) CreateSelfSignedCertificate(label, dn, hostname string) error { func (ks *KeyStore) CreateSelfSignedCertificate(label, dn, hostname string) error {
out, _, err := command.Run(ks.command, "-cert", "-create", "-db", ks.Filename, "-pw", ks.Password, "-label", label, "-dn", dn, "-san_dnsname", hostname, "-size 2048 -sig_alg sha256 -eku serverAuth") out, _, err := command.Run(ks.command, "-cert", "-create", "-db", ks.Filename, "-pw", ks.Password, "-label", label, "-dn", dn, "-san_dnsname", hostname)
if err != nil { if err != nil {
return fmt.Errorf("error running \"%v -cert -create\": %v %s", ks.command, err, out) return fmt.Errorf("error running \"%v -cert -create\": %v %s", ks.command, err, out)
} }
@@ -207,7 +207,7 @@ func (ks *KeyStore) RenameCertificate(from, to string) error {
// #nosec G204 // #nosec G204
cmd := exec.Command("/opt/mqm/gskit8/bin/gsk8capicmd_64", "-cert", "-rename", "-db", ks.Filename, "-pw", ks.Password, "-label", from, "-new_label", to) cmd := exec.Command("/opt/mqm/gskit8/bin/gsk8capicmd_64", "-cert", "-rename", "-db", ks.Filename, "-pw", ks.Password, "-label", from, "-new_label", to)
cmd.Env = append(os.Environ(), "LD_LIBRARY_PATH=/opt/mqm/gskit8/lib64/:/opt/mqm/gskit8/lib") cmd.Env = append(os.Environ(), "LD_LIBRARY_PATH=/opt/mqm/gskit8/lib64/:/opt/mqm/gskit8/lib")
out, err := cmd.CombinedOutput() out, _, err := command.RunCmd(cmd)
if err != nil { if err != nil {
return fmt.Errorf("error running \"%v -cert -rename\": %v %s", "/opt/mqm/gskit8/bin/gsk8capicmd_64", err, out) return fmt.Errorf("error running \"%v -cert -rename\": %v %s", "/opt/mqm/gskit8/bin/gsk8capicmd_64", err, out)
} }

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2018, 2019 © Copyright IBM Corporation 2018
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2018, 2019 © Copyright IBM Corporation 2018
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ limitations under the License.
package metrics package metrics
import ( import (
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )

View File

@@ -23,7 +23,7 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
"github.com/ibm-messaging/mq-container/internal/ready" "github.com/ibm-messaging/mq-container/internal/ready"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2018, 2019 © Copyright IBM Corporation 2018
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
"github.com/ibm-messaging/mq-golang/ibmmq" "github.com/ibm-messaging/mq-golang/ibmmq"
"github.com/ibm-messaging/mq-golang/mqmetric" "github.com/ibm-messaging/mq-golang/mqmetric"
) )

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2018, 2019 © Copyright IBM Corporation 2018
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
"github.com/ibm-messaging/mq-golang/mqmetric" "github.com/ibm-messaging/mq-golang/mqmetric"
) )

328
internal/mqini/mqini.go Normal file
View File

@@ -0,0 +1,328 @@
/*
© 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"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"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
}
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.
func AddStanzas(qmname string) error {
//find the qmgr directory.
qm, err := GetQueueManager(qmname)
if err != nil {
return err
}
qmgrDir = filepath.Join(qm.Prefix, "qmgrs", qm.Directory)
//Find the users ini configuration file
files := getIniFileList()
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)
}
if len(files) == 0 {
//no ini file update required.
return nil
}
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.
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
if err != nil {
return err
}
err = writeConfigStanzas(qmConfig, atConfig)
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 {
fileList := []string{}
filepath.Walk("/etc/mqm", func(path string, f os.FileInfo, err error) error {
if strings.HasSuffix(path, ".ini") {
fileList = append(fileList, path)
}
return nil
})
return fileList
}
//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.
iniFileBytes, err := ioutil.ReadFile(filepath.Join(qmgrDir, "qm.ini"))
if err != nil {
return "", "", err
}
qminiConfigStr = string(iniFileBytes)
iniFileBytes, err = ioutil.ReadFile(filepath.Join(qmgrDir, "mqat.ini"))
if err != nil {
return "", "", err
}
mqatiniConfigStr = string(iniFileBytes)
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 strings.Contains(scanner.Text(), ":") {
consumetoAppend = false
consumeToMerge = false
stanza = scanner.Text()
//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]
sb.WriteString(scanner.Text() + "\n")
stanzaListAppend[stanza] = sb
}
if consumeToMerge {
sb := stanzaListMerge[stanza]
sb.WriteString(scanner.Text() + "\n")
stanzaListMerge[stanza] = sb
}
}
}
//merge if stanza exits.
if len(stanzaListMerge) > 0 {
for key := range stanzaListMerge {
toWrite, filename := ValidateStanzaToWrite(key)
if toWrite {
attrList := stanzaListMerge[key]
switch filename {
case "qm.ini":
qminiConfigStr = prepareStanzasToMerge(key, attrList, qminiConfigStr)
case "mqat.ini":
mqatiniConfigStr = prepareStanzasToMerge(key, attrList, mqatiniConfigStr)
default:
}
}
}
}
//append new stanzas.
if len(stanzaListAppend) > 0 {
for key := range stanzaListAppend {
attrList := stanzaListAppend[key]
if strings.Contains(strings.Join(stanzasMQATINI, ", "), strings.TrimSuffix(strings.TrimSpace(key), ":")) {
mqatiniConfigStr = prepareStanzasToAppend(key, attrList, mqatiniConfigStr)
} else {
qminiConfigStr = prepareStanzasToAppend(key, attrList, qminiConfigStr)
}
}
}
return qminiConfigStr, mqatiniConfigStr, nil
}
//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, ":") {
stanza = stanza[:len(stanza)-1]
}
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, 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.
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.
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.
re := regexp.MustCompile(key)
newVal := key + "\n" + attrLine
iniConfig = re.ReplaceAllString(iniConfig, newVal)
}
}
return iniConfig
}
//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
}
err = ioutil.WriteFile(filepath.Join(qmgrDir, "mqat.ini"), []byte(atConfig), 0644)
if err != nil {
return err
}
return nil
}

View File

@@ -13,19 +13,58 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package mqinimerge package mqini
import ( import (
"bufio" "bufio"
"fmt"
"io/ioutil" "io/ioutil"
"os"
"path/filepath"
"strings" "strings"
"testing" "testing"
"time"
) )
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) { func TestIniFileStanzas(t *testing.T) {
PopulateAllAvailableStanzas() PopulateAllAvailableStanzas()
@@ -48,6 +87,7 @@ func TestIniFileStanzas(t *testing.T) {
} }
func TestIniFile1Update(t *testing.T) { func TestIniFile1Update(t *testing.T) {
iniFileBytes, err := ioutil.ReadFile("test1qm.ini") iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
if err != nil { if err != nil {
t.Errorf("Unexpected error: [%s]\n", err.Error()) t.Errorf("Unexpected error: [%s]\n", err.Error())
@@ -64,20 +104,19 @@ func TestIniFile1Update(t *testing.T) {
t.Errorf("Expected stanza file not found: qm.ini\n") t.Errorf("Expected stanza file not found: qm.ini\n")
} }
count := 0 scanner := bufio.NewScanner(strings.NewReader(userconfig))
//we want this line to be present exactly one. scanner.Split(bufio.ScanLines)
for _, item := range qmConfig { for scanner.Scan() {
item = strings.TrimSpace(item) line := scanner.Text()
if strings.Contains(item, "mylib") { if !strings.Contains(qmConfig, line) {
count++ t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig)
break
} }
} }
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) { func TestIniFile2Update(t *testing.T) {
iniFileBytes, err := ioutil.ReadFile("test2qm.ini") iniFileBytes, err := ioutil.ReadFile("test2qm.ini")
if err != nil { if err != nil {
t.Errorf("Unexpected error: [%s]\n", err.Error()) t.Errorf("Unexpected error: [%s]\n", err.Error())
@@ -94,20 +133,19 @@ func TestIniFile2Update(t *testing.T) {
t.Errorf("Expected stanza file not found: qm.ini\n") t.Errorf("Expected stanza file not found: qm.ini\n")
} }
count := 0 scanner := bufio.NewScanner(strings.NewReader(userconfig))
//we want this line to be present exactly one. scanner.Split(bufio.ScanLines)
for _, item := range atConfig { for scanner.Scan() {
item = strings.TrimSpace(item) line := scanner.Text()
if strings.Contains(item, "amqsget") { if !strings.Contains(atConfig, line) {
count++ t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig)
break
} }
} }
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) { func TestIniFile3Update(t *testing.T) {
i := 0 i := 0
iniFileBytes, err := ioutil.ReadFile("test3qm.ini") iniFileBytes, err := ioutil.ReadFile("test3qm.ini")
if err != nil { if err != nil {
@@ -125,9 +163,6 @@ func TestIniFile3Update(t *testing.T) {
t.Errorf("Expected stanza file not found: mqat.ini\n") 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 := bufio.NewScanner(strings.NewReader(userconfig))
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
for scanner.Scan() { for scanner.Scan() {
@@ -135,63 +170,19 @@ func TestIniFile3Update(t *testing.T) {
i++ i++
//first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file. //first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file.
if i < 20 { if i < 20 {
if !strings.Contains(qmConfigStr, strings.TrimSpace(line)) { if !strings.Contains(qmConfig, line) {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfigStr) t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig)
} }
} else if i > 20 { } else if i > 20 {
if !strings.Contains(atConfigStr, line) { if !strings.Contains(atConfig, line) {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, atConfigStr) t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig)
} }
} }
} }
} }
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) { func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) {
exists, filename := ValidateStanzaToWrite(stanza) exists, filename := ValidateStanzaToWrite(stanza)
if exists != shouldexist { if exists != shouldexist {
t.Errorf("Stanza should exist %t but found was %t", shouldexist, exists) t.Errorf("Stanza should exist %t but found was %t", shouldexist, exists)
@@ -209,48 +200,3 @@ func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) {
} }
} }
} }
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)
}
}
})
}
}

View File

@@ -1,5 +1,5 @@
ApiExitLocal:    ApiExitLocal:   
Sequence=1 Sequence=1
Function=EntryPoint Function=EntryPoint
Module=/opt/mqm/exitlib.so Module=/opt/mylibs/mylib.so
Name=mylib Name=mylib

View File

@@ -1,8 +1,8 @@
ApiExitLocal:    ApiExitLocal:   
Sequence=1 Sequence=1
Function=EntryPoint Function=EntryPoint
Module=/opt/foo/foo.so Module=/opt/MQOpenTracing/MQOpenTracingExit.so
Name=FooExit Name=MQOpenTracingExit
Channels: Channels:
MQIBindType=FASTPATH MQIBindType=FASTPATH
Log: Log:

View File

@@ -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
}

View File

@@ -23,7 +23,7 @@ import (
"text/template" "text/template"
"github.com/ibm-messaging/mq-container/internal/command" "github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/internal/logger"
) )
// ProcessTemplateFile takes a Go templateFile, and processes it with the // ProcessTemplateFile takes a Go templateFile, and processes it with the

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2017, 2019 © Copyright IBM Corporation 2017
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
© Copyright IBM Corporation 2017, 2019 © Copyright IBM Corporation 2017
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -35,8 +35,8 @@ import (
pkcs "software.sslmate.com/src/go-pkcs12" pkcs "software.sslmate.com/src/go-pkcs12"
) )
// WebDefaultLabel is the default certificate label for the web console // IntegrationDefaultLabel is the default certificate label used by Cloud Integration Platform
const WebDefaultLabel = "default" const IntegrationDefaultLabel = "default"
// P12TrustStoreName is the name of the PKCS#12 truststore used by the webconsole // P12TrustStoreName is the name of the PKCS#12 truststore used by the webconsole
const P12TrustStoreName = "trust.p12" const P12TrustStoreName = "trust.p12"

View File

@@ -12,17 +12,17 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
image: ibmcom/mq:9.1.3.0-r3 image: ibmcom/mq:9.1.3.0-r2
manifests: manifests:
- image: ibmcom/mq:9.1.3.0-r3-amd64 - image: ibmcom/mq:9.1.3.0-r2-amd64
platform: platform:
architecture: amd64 architecture: amd64
os: linux os: linux
- image: ibmcom/mq:9.1.3.0-r3-ppc64le - image: ibmcom/mq:9.1.3.0-r2-ppc64le
platform: platform:
architecture: ppc64le architecture: ppc64le
os: linux os: linux
- image: ibmcom/mq:9.1.3.0-r3-s390x - image: ibmcom/mq:9.1.3.0-r2-s390x
platform: platform:
architecture: s390x architecture: s390x
os: linux os: linux

View File

@@ -14,15 +14,15 @@
image: ibmcom/mq:latest image: ibmcom/mq:latest
manifests: manifests:
- image: ibmcom/mq:9.1.4.0-r1-amd64 - image: ibmcom/mq:9.1.3.0-r2-amd64
platform: platform:
architecture: amd64 architecture: amd64
os: linux os: linux
- image: ibmcom/mq:9.1.4.0-r1-ppc64le - image: ibmcom/mq:9.1.3.0-r2-ppc64le
platform: platform:
architecture: ppc64le architecture: ppc64le
os: linux os: linux
- image: ibmcom/mq:9.1.4.0-r1-s390x - image: ibmcom/mq:9.1.3.0-r2-s390x
platform: platform:
architecture: s390x architecture: s390x
os: linux os: linux

View File

@@ -12,17 +12,17 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3 image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r2
manifests: manifests:
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-amd64 - image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r2-amd64
platform: platform:
architecture: amd64 architecture: amd64
os: linux os: linux
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-ppc64le - image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r2-ppc64le
platform: platform:
architecture: ppc64le architecture: ppc64le
os: linux os: linux
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-s390x - image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r2-s390x
platform: platform:
architecture: s390x architecture: s390x
os: linux os: linux

View File

@@ -1,28 +0,0 @@
# © Copyright IBM Corporation 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.
image: ibmcorp/mqadvanced-server-dev:9.1.4.0-r1
manifests:
- image: ibmcorp/mqadvanced-server-dev:9.1.4.0-r1-amd64
platform:
architecture: amd64
os: linux
- image: ibmcorp/mqadvanced-server-dev:9.1.4.0-r1-ppc64le
platform:
architecture: ppc64le
os: linux
- image: ibmcorp/mqadvanced-server-dev:9.1.4.0-r1-s390x
platform:
architecture: s390x
os: linux

View File

@@ -1,92 +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 mqini provides information about queue managers
package mqini
import (
"bufio"
"errors"
"os"
"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) {
_, err := os.Stat("/var/mqm/mqs.ini")
if err != nil {
// Don't run dspmqinf, which will generate an FDC if mqs.ini isn't there yet
return nil, errors.New("dspmqinf should not be run before crtmqdir")
}
// 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)
}
}

View File

@@ -1,64 +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 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)
}
})
}
}

View File

@@ -380,78 +380,6 @@ func runContainerOneShotWithVolume(t *testing.T, cli *client.Client, bind string
return rc, out return rc, out
} }
func startMultiVolumeQueueManager(t *testing.T, cli *client.Client, dataVol bool, qmsharedlogs string, qmshareddata string, env []string) (error, string, string) {
id := strconv.FormatInt(time.Now().UnixNano(), 10)
qmdata := createVolume(t, cli, id)
containerConfig := container.Config{
Image: imageName(),
Env: env,
}
var hostConfig container.HostConfig
if !dataVol {
hostConfig = container.HostConfig{}
} else if qmsharedlogs == "" && qmshareddata == "" {
hostConfig = getHostConfig(t, 1, "", "", qmdata.Name)
} else if qmsharedlogs == "" {
hostConfig = getHostConfig(t, 2, "", qmshareddata, qmdata.Name)
} else if qmshareddata == "" {
hostConfig = getHostConfig(t, 3, qmsharedlogs, "", qmdata.Name)
} else {
hostConfig = getHostConfig(t, 4, qmsharedlogs, qmshareddata, qmdata.Name)
}
networkingConfig := network.NetworkingConfig{}
qm, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name()+id)
if err != nil {
return err, "", ""
}
startContainer(t, cli, qm.ID)
return nil, qm.ID, qmdata.Name
}
func getHostConfig(t *testing.T, mounts int, qmsharedlogs string, qmshareddata string, qmdata string) container.HostConfig {
var hostConfig container.HostConfig
switch mounts {
case 1:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
},
}
case 2:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmshareddata + ":/mnt/mqm-data",
},
}
case 3:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmsharedlogs + ":/mnt/mqm-log",
},
}
case 4:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmsharedlogs + ":/mnt/mqm-log",
qmshareddata + ":/mnt/mqm-data",
},
}
}
return hostConfig
}
func startContainer(t *testing.T, cli *client.Client, ID string) { func startContainer(t *testing.T, cli *client.Client, ID string) {
t.Logf("Starting container: %v", ID) t.Logf("Starting container: %v", ID)
startOptions := types.ContainerStartOptions{} startOptions := types.ContainerStartOptions{}

View File

@@ -19,10 +19,13 @@ import (
"context" "context"
"fmt" "fmt"
"regexp" "regexp"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client" "github.com/docker/docker/client"
) )
@@ -62,6 +65,78 @@ func singleMultiInstanceQueueManager(t *testing.T, cli *client.Client, qmsharedl
qmsChannel <- QMChan{QMId: qmId, QMData: qmData} qmsChannel <- QMChan{QMId: qmId, QMData: qmData}
} }
func getHostConfig(t *testing.T, mounts int, qmsharedlogs string, qmshareddata string, qmdata string) container.HostConfig {
var hostConfig container.HostConfig
switch mounts {
case 1:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
},
}
case 2:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmshareddata + ":/mnt/mqm-data",
},
}
case 3:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmsharedlogs + ":/mnt/mqm-log",
},
}
case 4:
hostConfig = container.HostConfig{
Binds: []string{
coverageBind(t),
qmdata + ":/mnt/mqm",
qmsharedlogs + ":/mnt/mqm-log",
qmshareddata + ":/mnt/mqm-data",
},
}
}
return hostConfig
}
func startMultiVolumeQueueManager(t *testing.T, cli *client.Client, dataVol bool, qmsharedlogs string, qmshareddata string, env []string) (error, string, string) {
id := strconv.FormatInt(time.Now().UnixNano(), 10)
qmdata := createVolume(t, cli, id)
containerConfig := container.Config{
Image: imageName(),
Env: env,
}
var hostConfig container.HostConfig
if !dataVol {
hostConfig = container.HostConfig{}
} else if qmsharedlogs == "" && qmshareddata == "" {
hostConfig = getHostConfig(t, 1, "", "", qmdata.Name)
} else if qmsharedlogs == "" {
hostConfig = getHostConfig(t, 2, "", qmshareddata, qmdata.Name)
} else if qmshareddata == "" {
hostConfig = getHostConfig(t, 3, qmsharedlogs, "", qmdata.Name)
} else {
hostConfig = getHostConfig(t, 4, qmsharedlogs, qmshareddata, qmdata.Name)
}
networkingConfig := network.NetworkingConfig{}
qm, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name()+id)
if err != nil {
return err, "", ""
}
startContainer(t, cli, qm.ID)
return nil, qm.ID, qmdata.Name
}
func getActiveStandbyQueueManager(t *testing.T, cli *client.Client, qm1aId string, qm1bId string) (error, string, string) { func getActiveStandbyQueueManager(t *testing.T, cli *client.Client, qm1aId string, qm1bId string) (error, string, string) {
qm1aStatus := getQueueManagerStatus(t, cli, qm1aId, "QM1") qm1aStatus := getQueueManagerStatus(t, cli, qm1aId, "QM1")
qm1bStatus := getQueueManagerStatus(t, cli, qm1bId, "QM1") qm1bStatus := getQueueManagerStatus(t, cli, qm1bId, "QM1")

View File

@@ -1,6 +1,5 @@
.classpath .classpath
.gradle .gradle
*.class
.project .project
.settings .settings
bin bin

View File

@@ -26,25 +26,25 @@ limitations under the License.
<dependency> <dependency>
<groupId>com.ibm.mq</groupId> <groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId> <artifactId>com.ibm.mq.allclient</artifactId>
<version>9.1.3.0</version> <version>9.0.5.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>5.5.2</version> <version>5.3.2</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version> <version>5.3.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.platform</groupId> <groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console-standalone</artifactId> <artifactId>junit-platform-console-standalone</artifactId>
<version>1.5.2</version> <version>1.3.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -1,29 +0,0 @@
#!/bin/bash
# © Copyright IBM Corporation 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.
set -e
echo 'Building Developer JMS test image...' && echo -en 'travis_fold:start:build-devjmstest\\r'
make build-devjmstest
echo -en 'travis_fold:end:build-devjmstest\\r'
echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
make build-devserver
echo -en 'travis_fold:end:build-devserver\\r'
if [ "$BUILD_ALL" = true ] ; then
echo 'Building Production image...' && echo -en 'travis_fold:start:build-advancedserver\\r'
make build-advancedserver
echo -en 'travis_fold:end:build-advancedserver\\r'
fi

View File

@@ -1,54 +0,0 @@
#!/bin/bash
# © Copyright IBM Corporation 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.
set -e
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
echo "Not pushing as we are a pull request"
exit 0
fi
if [ ! -z $2 ]; then
export ARCH=$2
fi
function push_developer {
echo 'Pushing Developer image...' && echo -en 'travis_fold:start:push-devserver\\r'
make push-devserver
echo -en 'travis_fold:end:push-devserver\\r'
}
function push_production {
echo 'Pushing Production image...' && echo -en 'travis_fold:start:push-advancedserver\\r'
make push-advancedserver
echo -en 'travis_fold:end:push-advancedserver\\r'
}
# call relevant push function
if [ ! -z $1 ]; then
case "$1" in
developer) push_developer
;;
production) push_production
;;
*) echo "ERROR: Type ( developer | production ) must be passed to push.sh"
exit 1
;;
esac
else
echo "ERROR: Type ( developer | production ) must be passed to push.sh"
exit 1
fi

View File

@@ -1,124 +0,0 @@
#!/bin/bash
# © Copyright IBM Corporation 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.
set -e
# staging or production
TYPE=""
MANIFEST_FILE=manifest-9.1.4.yaml
# set type of release
if [ ! -z $1 ]; then
case "$1" in
staging) TYPE=$1
;;
production) TYPE=$1
;;
*) echo "ERROR: Release type ( staging | production ) must passed to release.sh"
exit 1
;;
esac
else
echo "ERROR: Release type ( staging | production ) must passed to release.sh"
exit 1
fi
## Pull all images from default repository
ARCH=amd64 make pull-devserver
ARCH=ppc64le make pull-devserver
ARCH=s390x make pull-devserver
ARCH=amd64 make pull-advancedserver
ARCH=ppc64le make pull-advancedserver
ARCH=s390x make pull-advancedserver
function set_staging_registry {
export MQ_DELIVERY_REGISTRY_HOSTNAME=$MQ_STAGING_REGISTRY
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
export MQ_DELIVERY_REGISTRY_USER=$MQ_STAGING_REGISTRY_USER
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_STAGING_REGISTRY_CREDENTIAL
}
function set_docker_hub {
export MQ_DELIVERY_REGISTRY_HOSTNAME=ibmcom
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
export MQ_DELIVERY_REGISTRY_USER=$MQ_DOCKERHUB_REGISTRY_USER
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_DOCKERHUB_REGISTRY_CREDENTIAL
}
function set_docker_store {
export MQ_DELIVERY_REGISTRY_HOSTNAME=ibmcorp
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
export MQ_DELIVERY_REGISTRY_USER=$MQ_DOCKERHUB_REGISTRY_USER
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_DOCKERHUB_REGISTRY_CREDENTIAL
}
function set_production_registry {
export MQ_DELIVERY_REGISTRY_HOSTNAME=$MQ_PRODUCTION_REGISTRY
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
export MQ_DELIVERY_REGISTRY_USER=$MQ_PRODUCTION_REGISTRY_USER
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_PRODUCTION_REGISTRY_CREDENTIAL
}
if [ "$TYPE" = "staging" ]; then
set_staging_registry
# push production images to staging registy
./travis-build-scripts/push.sh production amd64
./travis-build-scripts/push.sh production ppc64le
./travis-build-scripts/push.sh production s390x
elif [ "$TYPE" = "production" ]; then
# pull production images from staging
set_staging_registry
ARCH=amd64 make pull-advancedserver
ARCH=ppc64le make pull-advancedserver
ARCH=s390x make pull-advancedserver
# release developer images with fat manifests
set_docker_hub
ARCH=amd64 make push-devserver-dockerhub
ARCH=ppc64le make push-devserver-dockerhub
ARCH=s390x make push-devserver-dockerhub
curl -LO https://github.com/estesp/manifest-tool/releases/download/v0.9.0/manifest-tool-linux-amd64
chmod a+x manifest-tool-linux-amd64
docker login --username $MQ_DOCKERHUB_REGISTRY_USER --password $MQ_DOCKERHUB_REGISTRY_CREDENTIAL
./manifest-tool-linux-amd64 push from-spec manifests/dockerhub/$MANIFEST_FILE
./manifest-tool-linux-amd64 push from-spec manifests/dockerhub/manifest-latest.yaml
set_docker_store
ARCH=amd64 make push-devserver-dockerhub
ARCH=ppc64le make push-devserver-dockerhub
ARCH=s390x make push-devserver-dockerhub
docker login --username $MQ_DOCKERHUB_REGISTRY_USER --password $MQ_DOCKERHUB_REGISTRY_CREDENTIAL
./manifest-tool-linux-amd64 push from-spec manifests/dockerstore/$MANIFEST_FILE
# release production image
set_production_registry
./travis-build-scripts/push.sh production amd64
./travis-build-scripts/push.sh production ppc64le
./travis-build-scripts/push.sh production s390x
fi

View File

@@ -1,36 +0,0 @@
#!/bin/bash
# © Copyright IBM Corporation 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.
set -e
if [ "$(uname -m)" = "x86_64" ] ; then export ARCH="amd64" ; else export ARCH=$(uname -m) ; fi
echo 'Downgrading Docker (if necessary)...' && echo -en 'travis_fold:start:docker-downgrade\\r'
eval "$DOCKER_DOWNGRADE"
echo -en 'travis_fold:end:docker-downgrade\\r'
## Build images
./travis-build-scripts/build.sh
## Test images
./travis-build-scripts/test.sh
## Push images
if [ "$BUILD_ALL" = true ] ; then
./travis-build-scripts/push.sh developer
./travis-build-scripts/push.sh production
fi

View File

@@ -1,33 +0,0 @@
#!/bin/bash
# © Copyright IBM Corporation 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.
set -e
echo 'Testing Developer image...' && echo -en 'travis_fold:start:test-devserver\\r'
make test-devserver
echo -en 'travis_fold:end:test-devserver\\r'
if [ "$BUILD_ALL" = true ] ; then
echo 'Testing Production image...' && echo -en 'travis_fold:start:test-advancedserver\\r'
make test-advancedserver
echo -en 'travis_fold:end:test-advancedserver\\r'
fi
echo 'Running gosec scan...' && echo -en 'travis_fold:start:gosec-scan\\r'
if [ "$ARCH" = "amd64" ] ; then
make gosec
else
echo "Gosec not available on ppc64le/s390x...skipping gosec scan"
fi
echo -en 'travis_fold:end:gosec-scan\\r'

View File

@@ -38,6 +38,7 @@
</openidConnectClient> </openidConnectClient>
<variable name="httpHost" value="*"/> <variable name="httpHost" value="*"/>
<variable name="managementMode" value="externallyprovisioned"/> <variable name="managementMode" value="externallyprovisioned"/>
<variable name="mqConsoleFrameAncestors" value="${env.MQ_HOSTS}"/>
<httpDispatcher enableWelcomePage="false" appOrContextRootMissingMessage='&lt;script&gt;document.location.href="/ibmmq/console";&lt;/script&gt;' /> <httpDispatcher enableWelcomePage="false" appOrContextRootMissingMessage='&lt;script&gt;document.location.href="/ibmmq/console";&lt;/script&gt;' />
<include location="tls.xml"/> <include location="tls.xml"/>
</server> </server>

View File

@@ -2,6 +2,6 @@
<server> <server>
<keyStore id="MQWebKeyStore" location="/run/runmqserver/tls/${env.AMQ_WEBKEYSTORE}" type="PKCS12" password="${env.AMQ_WEBKEYSTOREPW}"/> <keyStore id="MQWebKeyStore" location="/run/runmqserver/tls/${env.AMQ_WEBKEYSTORE}" type="PKCS12" password="${env.AMQ_WEBKEYSTOREPW}"/>
<keyStore id="MQWebTrustStore" location="/run/runmqserver/tls/trust.p12" type="PKCS12" password="${env.AMQ_WEBKEYSTOREPW}"/> <keyStore id="MQWebTrustStore" location="/run/runmqserver/tls/trust.p12" type="PKCS12" password="${env.AMQ_WEBKEYSTOREPW}"/>
<ssl id="thisSSLConfig" clientAuthenticationSupported="true" keyStoreRef="MQWebKeyStore" trustStoreRef="${env.AMQ_WEBTRUSTSTOREREF}" sslProtocol="TLSv1.2"/> <ssl id="thisSSLConfig" clientAuthenticationSupported="true" keyStoreRef="MQWebKeyStore" trustStoreRef="MQWebTrustStore" sslProtocol="TLSv1.2"/>
<sslDefault sslRef="thisSSLConfig"/> <sslDefault sslRef="thisSSLConfig"/>
</server> </server>