Compare commits
110 Commits
9.1.3
...
setuid-chk
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
829d9dfc58 | ||
|
|
f50ed4d9c7 | ||
|
|
9fba096d77 | ||
|
|
95be35d246 | ||
|
|
4fa7714361 | ||
|
|
e7fd10e7e6 | ||
|
|
98f01a40a7 | ||
|
|
f951bfaffa | ||
|
|
eb4a734ad0 | ||
|
|
5403c7af82 | ||
|
|
5a9f1d13e4 | ||
|
|
1b9f80a9af | ||
|
|
dd88fe5441 | ||
|
|
e6119202b4 | ||
|
|
3982cf3517 | ||
|
|
ecbe7b4f72 | ||
|
|
bf11bfbb60 | ||
|
|
cd69f6287f | ||
|
|
7dee4c82aa | ||
|
|
dc4675b99a | ||
|
|
ba493cbeb3 | ||
|
|
872050a2cd | ||
|
|
4737a8b660 | ||
|
|
9b81aedd9a | ||
|
|
c64c6fe95d | ||
|
|
a53fb7f49a | ||
|
|
d95e44f57c | ||
|
|
4b19af1dfe | ||
|
|
b4949aaf4f | ||
|
|
b9d48aa980 | ||
|
|
59baa97e91 | ||
|
|
394cb56ba0 | ||
|
|
62a2d6ef96 | ||
|
|
dcfebc38bd | ||
|
|
1ffc598064 | ||
|
|
fee0eac14c | ||
|
|
c56e305aec | ||
|
|
1bb39bc9fd | ||
|
|
c8de2df2cf | ||
|
|
7f14cc2751 | ||
|
|
35293e1b46 | ||
|
|
d2bc7b2adc | ||
|
|
f3777a499b | ||
|
|
f491d23d3b | ||
|
|
d4c3fad8c5 | ||
|
|
d9c8fc5c78 | ||
|
|
c1cbb62ee1 | ||
|
|
2fae0e2258 | ||
|
|
c9bac5b544 | ||
|
|
1a7a9236b7 | ||
|
|
6d69355ab9 | ||
|
|
49b4660360 | ||
|
|
ea38c9cd5c | ||
|
|
3ebd64f4da | ||
|
|
5e23d979d2 | ||
|
|
b64f8e8c21 | ||
|
|
2cbad648b9 | ||
|
|
88bcaaecc3 | ||
|
|
176a023a99 | ||
|
|
7f7883a312 | ||
|
|
84ea13eef2 | ||
|
|
4cab3e8d3b | ||
|
|
98ddca52ca | ||
|
|
3ba37b2b2b | ||
|
|
b4a3d7d732 | ||
|
|
3d5317f3da | ||
|
|
5891f170c8 | ||
|
|
f94d1b8af5 | ||
|
|
956b4a8e49 | ||
|
|
ce184408df | ||
|
|
140db42675 | ||
|
|
28b723d6cf | ||
|
|
61c909f551 | ||
|
|
ffda647cdf | ||
|
|
5897d6a644 | ||
|
|
34f7a57c5d | ||
|
|
5b5951ec3c | ||
|
|
b20761cea0 | ||
|
|
5449622d2a | ||
|
|
dd31fb37c3 | ||
|
|
2e453f2257 | ||
|
|
1f4528d597 | ||
|
|
c83aeb17c0 | ||
|
|
5a18280057 | ||
|
|
8e380b94f4 | ||
|
|
ebe8b7a6f0 | ||
|
|
ed4466d934 | ||
|
|
37601187b2 | ||
|
|
366d406f57 | ||
|
|
68ad98fc49 | ||
|
|
65edac267e | ||
|
|
ad0046ab01 | ||
|
|
c3fbc5816e | ||
|
|
11890d887b | ||
|
|
ac50d46c78 | ||
|
|
de298a4aad | ||
|
|
4de32ab8d2 | ||
|
|
8505579b37 | ||
|
|
7c59d647f5 | ||
|
|
8d8e4e4403 | ||
|
|
52b4eeea32 | ||
|
|
28291306cb | ||
|
|
4da7c60aee | ||
|
|
1ae24263ad | ||
|
|
d6248424a1 | ||
|
|
455c67ad3d | ||
|
|
f6ea588349 | ||
|
|
60fe631616 | ||
|
|
221796f746 | ||
|
|
97941bc87c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,3 +12,4 @@ vendor/github.com/prometheus/client_model/.classpath
|
||||
vendor/github.com/prometheus/client_model/.project
|
||||
vendor/github.com/prometheus/client_model/.settings*
|
||||
gosec_results.json
|
||||
internal/qmgrauth/qmgroam/patch
|
||||
|
||||
94
.travis.yml
94
.travis.yml
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2018, 2019
|
||||
# © Copyright IBM Corporation 2018, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,69 +12,77 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
dist: xenial
|
||||
# Temporarily removing dist tag as not supported by power build
|
||||
# dist: xenial
|
||||
|
||||
sudo: required
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.10"
|
||||
- "1.13.15"
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
go_import_path: "github.com/ibm-messaging/mq-container"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- downloads
|
||||
# cache:
|
||||
# directories:
|
||||
# - downloads
|
||||
|
||||
env:
|
||||
global:
|
||||
- RELEASE="r2"
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: build and test
|
||||
- stage: basic-build
|
||||
if: branch != private-master AND tag IS blank
|
||||
name: "Basic AMD64 build"
|
||||
os: linux
|
||||
env:
|
||||
- BASE_IMAGE=ubuntu:16.04
|
||||
- DOCKER_DOWNGRADE="echo nothing to be done"
|
||||
- env:
|
||||
- BASE_IMAGE=centos:7
|
||||
- DOCKER_DOWNGRADE="echo nothing to be done"
|
||||
- if: type IN (pull_request) OR tag IS present
|
||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_920_ARCHIVE_REPOSITORY_DEV_AMD64
|
||||
script: bash -e travis-build-scripts/run.sh
|
||||
- stage: build
|
||||
if: branch = private-master OR tag =~ ^release-candidate*
|
||||
name: "Multi-Arch AMD64 build"
|
||||
os: linux
|
||||
env:
|
||||
- BASE_IMAGE=ubuntu:16.04
|
||||
- DOCKER_DOWNGRADE="docker save -o images.tar mqadvanced-server-dev mq-dev-jms-test &&
|
||||
sudo apt-get autoremove -y docker-ce &&
|
||||
curl -fsSL \"https://apt.dockerproject.org/gpg\" | sudo apt-key add - &&
|
||||
sudo apt-add-repository \"deb https://apt.dockerproject.org/repo ubuntu-$(lsb_release -cs) main\" &&
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install docker-engine=1.12.6-0~ubuntu-$(lsb_release -cs) &&
|
||||
docker load -q -i images.tar &&
|
||||
export DOCKER_API_VERSION=\"1.24\""
|
||||
|
||||
- BUILD_ALL=true
|
||||
- MQ_ARCHIVE_REPOSITORY=$MQ_920_ARCHIVE_REPOSITORY_AMD64
|
||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_920_ARCHIVE_REPOSITORY_DEV_AMD64
|
||||
script: bash -e travis-build-scripts/run.sh
|
||||
# - if: branch = private-master OR tag =~ ^release-candidate*
|
||||
# name: "Multi-Arch PPC64LE build"
|
||||
# os: linux-ppc64le
|
||||
# env:
|
||||
# - BUILD_ALL=true
|
||||
# - TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
||||
# # - MQ_ARCHIVE_REPOSITORY=$MQ_920_ARCHIVE_REPOSITORY_PPC64LE
|
||||
# - MQ_ARCHIVE_REPOSITORY_DEV=$MQ_920_ARCHIVE_REPOSITORY_DEV_PPC64LE
|
||||
# script: bash -e travis-build-scripts/run.sh
|
||||
- stage: build
|
||||
if: branch = private-master OR tag =~ ^release-candidate*
|
||||
name: "Multi-Arch S390X build"
|
||||
os: linux-s390
|
||||
env:
|
||||
- BUILD_ALL=true
|
||||
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
||||
- MQ_ARCHIVE_REPOSITORY=$MQ_920_ARCHIVE_REPOSITORY_S390X
|
||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_920_ARCHIVE_REPOSITORY_DEV_S390X
|
||||
script: bash -e travis-build-scripts/run.sh
|
||||
- stage: push-manifest
|
||||
if: branch = private-master OR tag =~ ^release-candidate*
|
||||
name: "Push Manifest-list to registry"
|
||||
script: make push-manifest
|
||||
before_install:
|
||||
- ./install-build-deps-ubuntu.sh
|
||||
- make install-build-deps
|
||||
- make install-credential-helper
|
||||
|
||||
install:
|
||||
- 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'
|
||||
# Use the containerized build explicitly
|
||||
- make build-devserver-ctr
|
||||
- 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'
|
||||
before_script: echo nothing
|
||||
|
||||
after_success:
|
||||
- make lint
|
||||
|
||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,5 +1,21 @@
|
||||
# Change log
|
||||
|
||||
## 9.2.0.0 (2020-07-23)
|
||||
|
||||
* Updated to [MQ version 9.2.0.0](https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.2.0/com.ibm.mq.pro.doc/q113110_.htm)
|
||||
* Use `-ic` arguments with `crtmqm` to process MQSC files in `/etc/mqm`. Replaces previous use of "runmqsc" commands
|
||||
|
||||
## 9.1.5.0 (2020-04-02)
|
||||
|
||||
* Updated to MQ version 9.1.5.0
|
||||
* Can now run as a random user, instead of the "mqm" user, which has now been removed. This adds compatability for the [Red Hat OpenShift restricted SCC](https://docs.openshift.com/container-platform/4.3/authentication/managing-security-context-constraints.html#security-context-constraints-about_configuring-internal-oauth). The default image UID is `1001`.
|
||||
|
||||
## 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)
|
||||
|
||||
* Updated to MQ version 9.1.3.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2015, 2019
|
||||
# © Copyright IBM Corporation 2015, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,98 +12,117 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG BASE_IMAGE=registry.redhat.io/ubi8/ubi-minimal
|
||||
ARG BASE_TAG=8.2-349
|
||||
ARG GO_WORKDIR=/go/src/github.com/ibm-messaging/mq-container
|
||||
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/9.2.0.0-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"
|
||||
###############################################################################
|
||||
# Build stage to build Go code
|
||||
###############################################################################
|
||||
FROM registry.access.redhat.com/devtools/go-toolset-7-rhel7 as builder
|
||||
# FROM docker.io/centos/go-toolset-7-centos7 as builder
|
||||
FROM golang:1.13.15 as builder
|
||||
# The URL to download the MQ installer from in tar.gz format
|
||||
# This assumes an archive containing the MQ RPM install packages
|
||||
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev912_linux_x86-64.tar.gz"
|
||||
# This assumes an archive containing the MQ Non-Install packages
|
||||
ARG MQ_URL
|
||||
ARG IMAGE_REVISION="Not specified"
|
||||
ARG IMAGE_SOURCE="Not specified"
|
||||
ARG IMAGE_TAG="Not specified"
|
||||
ARG MQM_UID=888
|
||||
ARG GO_WORKDIR
|
||||
USER 0
|
||||
COPY install-mq.sh /usr/local/bin/
|
||||
RUN chmod a+x /usr/local/bin/install-mq.sh \
|
||||
RUN mkdir /opt/mqm \
|
||||
&& chmod a+x /usr/local/bin/install-mq.sh \
|
||||
&& sleep 1 \
|
||||
&& MQ_PACKAGES="MQSeriesRuntime-*.rpm MQSeriesSDK-*.rpm MQSeriesSamples*.rpm" install-mq.sh $MQM_UID
|
||||
WORKDIR /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/
|
||||
&& INSTALL_SDK=1 install-mq.sh \
|
||||
&& chown -R 1001:root /opt/mqm/*
|
||||
WORKDIR $GO_WORKDIR/
|
||||
COPY cmd/ ./cmd
|
||||
COPY internal/ ./internal
|
||||
COPY pkg/ ./pkg
|
||||
COPY vendor/ ./vendor
|
||||
ENV PATH="${PATH}:/opt/rh/go-toolset-7/root/usr/bin" \
|
||||
CGO_CFLAGS="-I/opt/mqm/inc/" \
|
||||
ENV CGO_CFLAGS="-I/opt/mqm/inc/" \
|
||||
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 ./cmd/chkmqready/
|
||||
RUN go build ./cmd/chkmqhealthy/
|
||||
RUN go build ./cmd/runmqdevserver/
|
||||
RUN go build -buildmode=c-shared -o amqpasdev.so ./internal/qmgrauth/pas.go
|
||||
RUN go test -v ./cmd/runmqdevserver/...
|
||||
RUN go test -v ./cmd/runmqserver/
|
||||
RUN go test -v ./cmd/chkmqready/
|
||||
RUN go test -v ./cmd/chkmqhealthy/
|
||||
RUN go test -v ./pkg/...
|
||||
RUN go test -v ./internal/...
|
||||
RUN go vet ./cmd/... ./internal/...
|
||||
|
||||
###############################################################################
|
||||
# Main build stage, to build MQ image
|
||||
###############################################################################
|
||||
FROM registry.access.redhat.com/ubi7/ubi-minimal AS mq-server
|
||||
FROM $BASE_IMAGE:$BASE_TAG AS mq-server
|
||||
# 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_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="ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-web ibmmq-ams"
|
||||
ARG MQM_UID=888
|
||||
ARG MQ_URL
|
||||
ARG BASE_IMAGE
|
||||
ARG BASE_TAG
|
||||
ARG GO_WORKDIR
|
||||
LABEL summary="IBM MQ Advanced Server"
|
||||
LABEL description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the world’s most successful enterprises"
|
||||
LABEL vendor="IBM"
|
||||
LABEL maintainer="IBM"
|
||||
LABEL distribution-scope="private"
|
||||
LABEL authoritative-source-url="https://www.ibm.com/software/passportadvantage/"
|
||||
LABEL url="https://www.ibm.com/products/mq/advanced"
|
||||
LABEL io.openshift.tags="mq messaging"
|
||||
LABEL io.k8s.display-name="IBM MQ Advanced Server"
|
||||
LABEL io.k8s.description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the world’s most successful enterprises"
|
||||
LABEL base-image=$BASE_IMAGE
|
||||
LABEL base-image-release=$BASE_TAG
|
||||
COPY install-mq.sh /usr/local/bin/
|
||||
COPY install-mq-server-prereqs.sh /usr/local/bin/
|
||||
# Install MQ. To avoid a "text file busy" error here, we sleep before installing.
|
||||
RUN env && chmod u+x /usr/local/bin/install-*.sh \
|
||||
RUN env \
|
||||
&& mkdir /opt/mqm \
|
||||
&& chmod u+x /usr/local/bin/install-*.sh \
|
||||
&& sleep 1 \
|
||||
&& install-mq-server-prereqs.sh $MQM_UID \
|
||||
&& install-mq.sh $MQM_UID
|
||||
&& install-mq-server-prereqs.sh \
|
||||
&& install-mq.sh \
|
||||
&& /opt/mqm/bin/security/amqpamcf \
|
||||
&& chown -R 1001:root /opt/mqm/*
|
||||
# Create a directory for runtime data from runmqserver
|
||||
RUN mkdir -p /run/runmqserver \
|
||||
&& chown mqm:mqm /run/runmqserver
|
||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/runmqserver /usr/local/bin/
|
||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/chkmq* /usr/local/bin/
|
||||
&& chown 1001:root /run/runmqserver
|
||||
COPY --from=builder $GO_WORKDIR/runmqserver /usr/local/bin/
|
||||
COPY --from=builder $GO_WORKDIR/chkmq* /usr/local/bin/
|
||||
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
|
||||
# Copy web XML files
|
||||
COPY web /etc/mqm/web
|
||||
COPY etc/mqm/*.tpl /etc/mqm/
|
||||
RUN chmod ug+x /usr/local/bin/runmqserver \
|
||||
&& chown mqm:mqm /usr/local/bin/*mq* \
|
||||
&& chmod ug+xs /usr/local/bin/chkmq* \
|
||||
&& chown -R mqm:mqm /etc/mqm/* \
|
||||
&& install --directory --mode 0775 --owner mqm --group root /run/runmqserver \
|
||||
&& chown 1001:root /usr/local/bin/*mq* \
|
||||
&& chmod ug+x /usr/local/bin/chkmq* \
|
||||
&& chown -R 1001:root /etc/mqm/* \
|
||||
&& install --directory --mode 2775 --owner 1001 --group root /run/runmqserver \
|
||||
&& touch /run/termination-log \
|
||||
&& chown mqm:root /run/termination-log \
|
||||
&& chmod 0660 /run/termination-log
|
||||
&& chown 1001:root /run/termination-log \
|
||||
&& chmod 0660 /run/termination-log \
|
||||
&& chmod -R g+w /etc/mqm/web
|
||||
# Always use port 1414 for MQ & 9157 for the metrics
|
||||
EXPOSE 1414 9157 9443
|
||||
ENV MQ_OVERRIDE_DATA_PATH=/mnt/mqm/data MQ_OVERRIDE_INSTALLATION_NAME=Installation1 MQ_USER_NAME="mqm" PATH="${PATH}:/opt/mqm/bin"
|
||||
ENV MQ_GRACE_PERIOD=30
|
||||
ENV LANG=en_US.UTF-8 AMQ_DIAGNOSTIC_MSG_SEVERITY=1 AMQ_ADDITIONAL_JSON_LOG=1 LOG_FORMAT=basic
|
||||
USER $MQM_UID
|
||||
# We can run as any UID
|
||||
USER 1001
|
||||
ENV MQ_CONNAUTH_USE_HTP=false
|
||||
ENTRYPOINT ["runmqserver"]
|
||||
|
||||
###############################################################################
|
||||
# Add default developer config
|
||||
###############################################################################
|
||||
FROM mq-server AS mq-dev-server
|
||||
ARG MQM_UID=888
|
||||
ARG BASE_IMAGE
|
||||
ARG BASE_TAG
|
||||
ARG GO_WORKDIR
|
||||
# Enable MQ developer default configuration
|
||||
ENV MQ_DEV=true
|
||||
# Default administrator password
|
||||
ENV MQ_ADMIN_PASSWORD=passw0rd
|
||||
LABEL summary="IBM MQ Advanced for Developers Server"
|
||||
LABEL description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the world’s most successful enterprises"
|
||||
LABEL vendor="IBM"
|
||||
@@ -113,30 +132,32 @@ LABEL url="https://www.ibm.com/products/mq/advanced"
|
||||
LABEL io.openshift.tags="mq messaging"
|
||||
LABEL io.k8s.display-name="IBM MQ Advanced for Developers Server"
|
||||
LABEL io.k8s.description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the world’s most successful enterprises"
|
||||
LABEL base-image=$BASE_IMAGE
|
||||
LABEL base-image-release=$BASE_TAG
|
||||
USER 0
|
||||
COPY --from=builder $GO_WORKDIR/amqpas* /opt/mqm/lib64/
|
||||
COPY etc/mqm/*.ini /etc/mqm/
|
||||
COPY etc/mqm/mq.htpasswd /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/mq.htpasswd
|
||||
COPY incubating/mqadvanced-server-dev/install-extra-packages.sh /usr/local/bin/
|
||||
RUN chmod u+x /usr/local/bin/install-extra-packages.sh \
|
||||
&& sleep 1 \
|
||||
&& install-extra-packages.sh
|
||||
# WARNING: This is what allows the mqm user to change the password of any other user
|
||||
# It's used by runmqdevserver to change the admin/app passwords.
|
||||
RUN echo "mqm ALL = NOPASSWD: /usr/sbin/chpasswd" > /etc/sudoers.d/mq-dev-config
|
||||
## Add admin and app users, and set a default password for admin
|
||||
RUN useradd admin -G mqm \
|
||||
&& groupadd mqclient \
|
||||
&& useradd app -G mqclient \
|
||||
&& echo admin:$MQ_ADMIN_PASSWORD | chpasswd
|
||||
# Create a directory for runtime data from runmqserver
|
||||
RUN mkdir -p /run/runmqdevserver \
|
||||
&& chown mqm:mqm /run/runmqdevserver
|
||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/runmqdevserver /usr/local/bin/
|
||||
&& chown 1001:root /run/runmqdevserver
|
||||
COPY --from=builder $GO_WORKDIR/runmqdevserver /usr/local/bin/
|
||||
# Copy template files
|
||||
COPY incubating/mqadvanced-server-dev/*.tpl /etc/mqm/
|
||||
# Copy web XML files for default developer configuration
|
||||
COPY incubating/mqadvanced-server-dev/web /etc/mqm/web
|
||||
RUN chown -R mqm:mqm /etc/mqm/* \
|
||||
RUN chown -R 1001:root /etc/mqm/* \
|
||||
&& chmod -R g+w /etc/mqm/web \
|
||||
&& chmod +x /usr/local/bin/runmq* \
|
||||
&& install --directory --mode 0775 --owner mqm --group root /run/runmqdevserver
|
||||
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1
|
||||
USER $MQM_UID
|
||||
&& install --directory --mode 2775 --owner 1001 --group root /run/runmqdevserver
|
||||
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1 MQ_GENERATE_CERTIFICATE_HOSTNAME=localhost
|
||||
ENV LD_LIBRARY_PATH=/opt/mqm/lib64
|
||||
ENV MQS_PERMIT_UNKNOWN_ID=true
|
||||
ENV MQ_CONNAUTH_USE_HTP=true
|
||||
USER 1001
|
||||
ENTRYPOINT ["runmqdevserver"]
|
||||
|
||||
327
Makefile
327
Makefile
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2017, 2019
|
||||
# © Copyright IBM Corporation 2017, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -16,47 +16,66 @@
|
||||
# Conditional variables - you can override the values of these variables from
|
||||
# the command line
|
||||
###############################################################################
|
||||
# MQ_VERSION is the fully qualified MQ version number to build
|
||||
MQ_VERSION ?= 9.1.3.0
|
||||
# RELEASE shows what release of the container code has been built
|
||||
RELEASE ?= 1
|
||||
RELEASE ?=
|
||||
# MQ_VERSION is the fully qualified MQ version number to build
|
||||
MQ_VERSION ?= 9.2.0.0
|
||||
# MQ_ARCHIVE_REPOSITORY is a remote repository from which to pull the MQ_ARCHIVE (if required)
|
||||
MQ_ARCHIVE_REPOSITORY ?=
|
||||
# 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
|
||||
# be installed. The default value is derived from MQ_VERSION, BASE_IMAGE and architecture
|
||||
# Does not apply to MQ Advanced for Developers.
|
||||
MQ_ARCHIVE ?= IBM_MQ_$(MQ_VERSION_VRM)_$(MQ_ARCHIVE_TYPE)_$(MQ_ARCHIVE_ARCH).tar.gz
|
||||
# be installed. Does not apply to MQ Advanced for Developers
|
||||
MQ_ARCHIVE ?= IBM_MQ_$(MQ_VERSION_VRM)_$(MQ_ARCHIVE_TYPE)_$(MQ_ARCHIVE_ARCH)_NOINST.tar.gz
|
||||
# MQ_ARCHIVE_DEV is the name of the file, under the downloads directory, from which MQ Advanced
|
||||
# for Developers can be installed
|
||||
MQ_ARCHIVE_DEV ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
|
||||
MQ_ARCHIVE_DEV ?= $(MQ_VERSION)-IBM-MQ-Advanced-for-Developers-Non-Install-$(MQ_ARCHIVE_DEV_TYPE)$(MQ_ARCHIVE_DEV_ARCH).tar.gz
|
||||
# MQ_SDK_ARCHIVE specifies the archive to use for building the golang programs. Defaults vary on developer or advanced.
|
||||
MQ_SDK_ARCHIVE ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
|
||||
# Options to `go test` for the Docker tests
|
||||
TEST_OPTS_DOCKER ?=
|
||||
# Timeout for the Docker tests
|
||||
TEST_TIMEOUT_DOCKER ?= 30m
|
||||
# MQ_IMAGE_ADVANCEDSERVER is the name of the built MQ Advanced image
|
||||
MQ_IMAGE_ADVANCEDSERVER ?=mqadvanced-server
|
||||
MQ_IMAGE_ADVANCEDSERVER ?=ibm-mqadvanced-server
|
||||
# MQ_IMAGE_DEVSERVER is the name of the built MQ Advanced for Developers image
|
||||
MQ_IMAGE_DEVSERVER ?=mqadvanced-server-dev
|
||||
MQ_IMAGE_DEVSERVER ?=ibm-mqadvanced-server-dev
|
||||
# MQ_TAG is the tag of the built MQ Advanced image & MQ Advanced for Developers image
|
||||
MQ_TAG ?=$(MQ_VERSION)-$(ARCH)
|
||||
# DOCKER is the Docker command to run. Defaults to "podman" if it's available, otherwise "docker"
|
||||
DOCKER ?= $(shell type -p podman || echo docker)
|
||||
# MQ_PACKAGES specifies the MQ packages (.deb or .rpm) to install. Defaults vary on base image.
|
||||
MQ_PACKAGES ?=MQSeriesRuntime-*.rpm MQSeriesServer-*.rpm MQSeriesJava*.rpm MQSeriesJRE*.rpm MQSeriesGSKit*.rpm MQSeriesMsg*.rpm MQSeriesSamples*.rpm MQSeriesWeb*.rpm MQSeriesAMS-*.rpm
|
||||
# MQM_UID is the UID to use for the "mqm" user
|
||||
MQM_UID ?= 888
|
||||
# COMMAND is the container command to run. "podman" or "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))
|
||||
# Tag to use for fat-manifest
|
||||
MQ_MANIFEST_TAG=$(MQ_VERSION)
|
||||
|
||||
###############################################################################
|
||||
# Other variables
|
||||
###############################################################################
|
||||
GO_PKG_DIRS = ./cmd ./internal ./test
|
||||
MQ_ARCHIVE_TYPE=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))
|
||||
MQ_ARCHIVE_DEV_TYPE=Linux
|
||||
# BUILD_SERVER_CONTAINER is the name of the web server container used at build time
|
||||
BUILD_SERVER_CONTAINER=build-server
|
||||
# NUM_CPU is the number of CPUs available to Docker. Used to control how many
|
||||
# test run in parallel
|
||||
NUM_CPU = $(or $(shell docker info --format "{{ .NCPU }}"),2)
|
||||
NUM_CPU ?= $(or $(shell docker info --format "{{ .NCPU }}"),2)
|
||||
# BASE_IMAGE_TAG is a normalized version of BASE_IMAGE, suitable for use in a Docker tag
|
||||
BASE_IMAGE_TAG=$(lastword $(subst /, ,$(subst :,-,$(BASE_IMAGE))))
|
||||
#BASE_IMAGE_TAG=$(subst /,-,$(subst :,-,$(BASE_IMAGE)))
|
||||
@@ -68,17 +87,9 @@ IMAGE_REVISION=$(shell git rev-parse HEAD)
|
||||
IMAGE_SOURCE=$(shell git config --get remote.origin.url)
|
||||
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.3 instead of 9.1.3.0
|
||||
# MQ_VERSION_VRM is MQ_VERSION with only the Version, Release and Modifier fields (no Fix field). e.g. 9.2.0 instead of 9.2.0.0
|
||||
MQ_VERSION_VRM=$(subst $(SPACE),.,$(wordlist 1,3,$(subst .,$(SPACE),$(MQ_VERSION))))
|
||||
|
||||
# Set variable if running on a Red Hat Enterprise Linux host
|
||||
ifneq ($(wildcard /etc/redhat-release),)
|
||||
REDHAT_RELEASE = $(shell cat /etc/redhat-release)
|
||||
ifeq "$(findstring Red Hat,$(REDHAT_RELEASE))" "Red Hat"
|
||||
RHEL_HOST = "true"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring Microsoft,$(shell uname -r)))
|
||||
DOWNLOADS_DIR=$(patsubst /mnt/c%,C:%,$(realpath ./downloads/))
|
||||
else ifneq (,$(findstring Windows,$(shell echo ${OS})))
|
||||
@@ -90,31 +101,40 @@ endif
|
||||
# Try to figure out which archive to use from the architecture
|
||||
ifeq "$(ARCH)" "amd64"
|
||||
MQ_ARCHIVE_ARCH=X86-64
|
||||
MQ_DEV_ARCH=x86-64
|
||||
MQ_ARCHIVE_DEV_ARCH=X64
|
||||
else ifeq "$(ARCH)" "ppc64le"
|
||||
MQ_ARCHIVE_ARCH=LE_POWER
|
||||
MQ_DEV_ARCH=ppcle
|
||||
MQ_ARCHIVE_ARCH=PPC64LE
|
||||
else ifeq "$(ARCH)" "s390x"
|
||||
MQ_ARCHIVE_ARCH=SYSTEM_Z
|
||||
MQ_DEV_ARCH=s390x
|
||||
MQ_ARCHIVE_ARCH=S390X
|
||||
endif
|
||||
# Archive names for IBM MQ Advanced for Developers
|
||||
MQ_ARCHIVE_DEV_9.1.0.0=mqadv_dev910_$(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.3.0=mqadv_dev913_$(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_TAG=$(MQ_VERSION)-$(RELEASE)-$(ARCH)
|
||||
EXTRA_LABELS=--label release=$(RELEASE)
|
||||
MQ_MANIFEST_TAG=$(MQ_VERSION)-$(RELEASE)
|
||||
endif
|
||||
MQ_IMAGE_FULL_RELEASE_NAME=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
|
||||
MQ_IMAGE_DEV_FULL_RELEASE_NAME=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG)
|
||||
|
||||
#setup variables for fat-manifests
|
||||
MQ_IMAGE_DEVSERVER_MANIFEST=$(MQ_IMAGE_DEVSERVER):$(MQ_MANIFEST_TAG)
|
||||
MQ_IMAGE_ADVANCEDSERVER_MANIFEST=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_MANIFEST_TAG)
|
||||
MQ_IMAGE_DEVSERVER_AMD64=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEVSERVER):$(MQ_MANIFEST_TAG)-amd64
|
||||
MQ_IMAGE_DEVSERVER_S390X=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEVSERVER):$(MQ_MANIFEST_TAG)-s390x
|
||||
MQ_IMAGE_ADVANCEDSERVER_AMD64=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_MANIFEST_TAG)-amd64
|
||||
MQ_IMAGE_ADVANCEDSERVER_S390X=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_MANIFEST_TAG)-s390x
|
||||
|
||||
###############################################################################
|
||||
# Build targets
|
||||
###############################################################################
|
||||
.PHONY: vars
|
||||
vars:
|
||||
@echo $(MQ_ARCHIVE_ARCH)
|
||||
@echo $(MQ_ARCHIVE_TYPE)
|
||||
@echo $(MQ_ARCHIVE)
|
||||
|
||||
.PHONY: default
|
||||
default: build-devserver test
|
||||
default: build-devserver
|
||||
|
||||
# Build all components (except incubating ones)
|
||||
.PHONY: all
|
||||
@@ -126,6 +146,9 @@ test-all: build-devjmstest test-devserver test-advancedserver
|
||||
.PHONY: devserver
|
||||
devserver: build-devserver build-devjmstest test-devserver
|
||||
|
||||
.PHONY: advancedserver
|
||||
advancedserver: build-advancedserver test-advancedserver
|
||||
|
||||
# Build incubating components
|
||||
.PHONY: incubating
|
||||
incubating: build-explorer
|
||||
@@ -133,12 +156,18 @@ incubating: build-explorer
|
||||
downloads/$(MQ_ARCHIVE_DEV):
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
|
||||
mkdir -p downloads
|
||||
cd downloads; curl -LO https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_ARCHIVE_DEV)
|
||||
ifneq "$(MQ_ARCHIVE_REPOSITORY_DEV)" "$(EMPTY)"
|
||||
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_SDK_ARCHIVE):
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
|
||||
downloads/$(MQ_ARCHIVE):
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced "$(MQ_VERSION)$(END)))
|
||||
mkdir -p downloads
|
||||
cd downloads; curl -LO https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_SDK_ARCHIVE)
|
||||
ifneq "$(MQ_ARCHIVE_REPOSITORY)" "$(EMPTY)"
|
||||
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY)" -o downloads/$(MQ_ARCHIVE)
|
||||
endif
|
||||
|
||||
.PHONY: downloads
|
||||
downloads: downloads/$(MQ_ARCHIVE_DEV) downloads/$(MQ_SDK_ARCHIVE)
|
||||
@@ -156,7 +185,7 @@ test-unit:
|
||||
test-advancedserver: test/docker/vendor
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
||||
docker inspect $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
|
||||
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) EXPECTED_LICENSE=Production go test -parallel $(NUM_CPU) $(TEST_OPTS_DOCKER)
|
||||
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) EXPECTED_LICENSE=Production go test -parallel $(NUM_CPU) -timeout $(TEST_TIMEOUT_DOCKER) $(TEST_OPTS_DOCKER)
|
||||
|
||||
.PHONY: build-devjmstest
|
||||
build-devjmstest:
|
||||
@@ -166,8 +195,9 @@ build-devjmstest:
|
||||
.PHONY: test-devserver
|
||||
test-devserver: test/docker/vendor
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_DEVSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
||||
|
||||
docker inspect $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)
|
||||
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG) EXPECTED_LICENSE=Developer DEV_JMS_IMAGE=$(DEV_JMS_IMAGE) IBMJRE=true go test -parallel $(NUM_CPU) -tags mqdev $(TEST_OPTS_DOCKER)
|
||||
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG) EXPECTED_LICENSE=Developer DEV_JMS_IMAGE=$(DEV_JMS_IMAGE) IBMJRE=true go test -parallel $(NUM_CPU) -timeout $(TEST_TIMEOUT_DOCKER) -tags mqdev $(TEST_OPTS_DOCKER)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@@ -196,138 +226,174 @@ test-advancedserver-cover: test/docker/vendor coverage
|
||||
tail -q -n +2 ./coverage/unit.cov ./coverage/docker.cov >> ./coverage/combined.cov
|
||||
go tool cover -html=./coverage/combined.cov -o ./coverage/combined.html
|
||||
|
||||
# Build an MQ image. The commands used are slightly different between Docker and Podman
|
||||
define build-mq
|
||||
# Create a temporary network to use for the build
|
||||
$(DOCKER) network create build
|
||||
# Start a web server to host the MQ downloadable (tar.gz) file
|
||||
$(DOCKER) run \
|
||||
--rm \
|
||||
--name $(BUILD_SERVER_CONTAINER) \
|
||||
--network build \
|
||||
--network-alias build \
|
||||
--volume $(DOWNLOADS_DIR):/usr/share/nginx/html:ro \
|
||||
--detach \
|
||||
docker.io/nginx:alpine
|
||||
$(if $(findstring docker,$(COMMAND)), @docker network create build,)
|
||||
$(if $(findstring docker,$(COMMAND)), @docker run --rm --name $(BUILD_SERVER_CONTAINER) --network build --network-alias build --volume $(DOWNLOADS_DIR):/usr/share/nginx/html:ro --detach docker.io/nginx:alpine,)
|
||||
$(eval EXTRA_ARGS=$(if $(findstring docker,$(COMMAND)), --network build --build-arg MQ_URL=http://build:80/$4, --volume $(DOWNLOADS_DIR):/var/downloads --build-arg MQ_URL=file:///var/downloads/$4))
|
||||
# Build the new image
|
||||
$(DOCKER) build \
|
||||
$(COMMAND) build \
|
||||
--tag $1:$2 \
|
||||
--file $3 \
|
||||
--network build \
|
||||
--build-arg MQ_URL=http://build:80/$4 \
|
||||
--build-arg MQ_PACKAGES="$(MQ_PACKAGES)" \
|
||||
$(EXTRA_ARGS) \
|
||||
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
|
||||
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
|
||||
--build-arg IMAGE_TAG="$1:$2" \
|
||||
--build-arg MQM_UID=$(MQM_UID) \
|
||||
--label version=$(MQ_VERSION) \
|
||||
--label name=$1 \
|
||||
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
|
||||
--label release="$(RELEASE)" \
|
||||
--label architecture="$(ARCH)" \
|
||||
--label run="docker run -d -e LICENSE=accept $1:$2" \
|
||||
--label vcs-ref=$(IMAGE_REVISION) \
|
||||
--label vcs-type=git \
|
||||
--label vcs-url=$(IMAGE_SOURCE) \
|
||||
$(EXTRA_LABELS) \
|
||||
--target $5 \
|
||||
. ; $(DOCKER) kill $(BUILD_SERVER_CONTAINER) && $(DOCKER) network rm build
|
||||
endef
|
||||
|
||||
define build-mq-ctr
|
||||
buildah/mq-buildah $1 $2 \
|
||||
--file /src/Dockerfile-server \
|
||||
--build-arg MQ_URL="file:///src/downloads/$3" \
|
||||
--build-arg MQ_PACKAGES="$(MQ_PACKAGES)" \
|
||||
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
|
||||
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
|
||||
--build-arg IMAGE_TAG="$1:$2" \
|
||||
--build-arg MQM_UID=$(MQM_UID) \
|
||||
--label version=$(MQ_VERSION) \
|
||||
--label name=$1 \
|
||||
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
|
||||
--label release="$(RELEASE)" \
|
||||
--label architecture="$(ARCH)" \
|
||||
--label run="docker run -d -e LICENSE=accept $1:$2" \
|
||||
--label vcs-ref=$(IMAGE_REVISION) \
|
||||
--label vcs-type=git \
|
||||
--label vcs-url=$(IMAGE_SOURCE) \
|
||||
--target $4
|
||||
.
|
||||
$(if $(findstring docker,$(COMMAND)), @docker kill $(BUILD_SERVER_CONTAINER))
|
||||
$(if $(findstring docker,$(COMMAND)), @docker network rm build)
|
||||
endef
|
||||
|
||||
DOCKER_SERVER_VERSION=$(shell docker version --format "{{ .Server.Version }}")
|
||||
DOCKER_CLIENT_VERSION=$(shell docker version --format "{{ .Client.Version }}")
|
||||
.PHONY: docker-version
|
||||
docker-version:
|
||||
PODMAN_VERSION=$(shell podman version --format "{{ .Version }}")
|
||||
.PHONY: command-version
|
||||
command-version:
|
||||
# If we're using Docker, then check it's recent enough to support multi-stage builds
|
||||
ifneq (,$(findstring docker,$(COMMAND)))
|
||||
@test "$(word 1,$(subst ., ,$(DOCKER_CLIENT_VERSION)))" -ge "17" || ("$(word 1,$(subst ., ,$(DOCKER_CLIENT_VERSION)))" -eq "17" && "$(word 2,$(subst ., ,$(DOCKER_CLIENT_VERSION)))" -ge "05") || (echo "Error: Docker client 17.05 or greater is required" && exit 1)
|
||||
@test "$(word 1,$(subst ., ,$(DOCKER_SERVER_VERSION)))" -ge "17" || ("$(word 1,$(subst ., ,$(DOCKER_SERVER_VERSION)))" -eq "17" && "$(word 2,$(subst ., ,$(DOCKER_CLIENT_VERSION)))" -ge "05") || (echo "Error: Docker server 17.05 or greater is required" && exit 1)
|
||||
|
||||
.PHONY: build-advancedserver
|
||||
ifdef RHEL_HOST
|
||||
# Build using Buildah inside a container on RHEL hosts
|
||||
build-advancedserver: build-advancedserver-ctr
|
||||
else
|
||||
build-advancedserver: build-advancedserver-host
|
||||
endif
|
||||
ifneq (,$(findstring podman,$(COMMAND)))
|
||||
@test "$(word 1,$(subst ., ,$(PODMAN_VERSION)))" -ge "1" || (echo "Error: Podman version 1.0 or greater is required" && exit 1)
|
||||
endif
|
||||
|
||||
.PHONY: build-advancedserver-host
|
||||
build-advancedserver-host: downloads/$(MQ_ARCHIVE) docker-version
|
||||
build-advancedserver-host: build-advancedserver
|
||||
|
||||
.PHONY: build-advancedserver
|
||||
build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) command-version
|
||||
$(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)
|
||||
|
||||
.PHONY: build-advancedserver-ctr
|
||||
build-advancedserver-ctr: downloads/$(MQ_ARCHIVE)
|
||||
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) in a container"$(END)))
|
||||
$(call build-mq-ctr,$(MQ_IMAGE_ADVANCEDSERVER),$(MQ_TAG),$(MQ_ARCHIVE),mq-server)
|
||||
.PHONY: build-devserver-host
|
||||
build-devserver-host: build-devserver
|
||||
|
||||
.PHONY: build-devserver
|
||||
ifdef RHEL_HOST
|
||||
# Build using Buildah inside a container on RHEL hosts
|
||||
build-devserver: build-devserver-ctr
|
||||
else
|
||||
build-devserver: build-devserver-host
|
||||
endif
|
||||
|
||||
.PHONY: build-devserver-host
|
||||
build-devserver-host: downloads/$(MQ_ARCHIVE_DEV) docker-version
|
||||
build-devserver: registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
|
||||
$(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)
|
||||
|
||||
.PHONY: build-devserver-ctr
|
||||
build-devserver-ctr: downloads/$(MQ_ARCHIVE_DEV)
|
||||
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG) in a container"$(END)))
|
||||
$(call build-mq-ctr,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),$(MQ_ARCHIVE_DEV),mq-dev-server)
|
||||
|
||||
.PHONY: build-advancedserver-cover
|
||||
build-advancedserver-cover: docker-version
|
||||
$(DOCKER) build --build-arg BASE_IMAGE=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) -t $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)-cover -f Dockerfile-server.cover .
|
||||
build-advancedserver-cover: registry-login command-version
|
||||
$(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
|
||||
build-explorer: downloads/$(MQ_ARCHIVE_DEV)
|
||||
build-explorer: registry-login downloads/$(MQ_ARCHIVE_DEV)
|
||||
$(call build-mq,mq-explorer,latest-$(ARCH),incubating/mq-explorer/Dockerfile,$(MQ_ARCHIVE_DEV),mq-explorer)
|
||||
|
||||
.PHONY: build-sdk
|
||||
build-sdk: downloads/$(MQ_ARCHIVE_DEV)
|
||||
build-sdk: registry-login downloads/$(MQ_ARCHIVE_DEV)
|
||||
$(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)
|
||||
|
||||
.PHONY: debug-vars
|
||||
debug-vars:
|
||||
.PHONY: registry-login
|
||||
registry-login:
|
||||
ifneq ($(REGISTRY_USER),)
|
||||
$(COMMAND) login -u $(REGISTRY_USER) -p $(REGISTRY_PASS) registry.redhat.io
|
||||
endif
|
||||
|
||||
.PHONY: log-build-env
|
||||
log-build-vars:
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Build environment"$(END)))
|
||||
@echo ARCH=$(ARCH)
|
||||
@echo MQ_VERSION=$(MQ_VERSION)
|
||||
@echo MQ_VERSION_VRM=$(MQ_VERSION_VRM)
|
||||
@echo MQ_ARCHIVE=$(MQ_ARCHIVE)
|
||||
@echo MQ_ARCHIVE_DEV=$(MQ_ARCHIVE_DEV)
|
||||
@echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER)
|
||||
@echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER)
|
||||
@echo COMMAND=$(COMMAND)
|
||||
@echo REGISTRY_USER=$(REGISTRY_USER)
|
||||
|
||||
.PHONY: log-build-env
|
||||
log-build-env: log-build-vars
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Build environment - $(COMMAND) info"$(END)))
|
||||
@echo Command version: $(shell $(COMMAND) --version)
|
||||
$(COMMAND) info
|
||||
|
||||
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: 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: push-manifest
|
||||
push-manifest: build-skopeo-container
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"** Determining the image digests **"$(END)))
|
||||
$(eval MQ_IMAGE_DEVSERVER_AMD64_DIGEST=$(shell $(COMMAND) run skopeo:latest --override-os linux --override-arch s390x inspect --creds $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) docker://$(MQ_IMAGE_DEVSERVER_AMD64) | jq -r .Digest))
|
||||
$(eval MQ_IMAGE_DEVSERVER_S390X_DIGEST=$(shell $(COMMAND) run skopeo:latest --override-os linux inspect --creds $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) docker://$(MQ_IMAGE_DEVSERVER_S390X) | jq -r .Digest))
|
||||
$(eval MQ_IMAGE_ADVANCEDSERVER_AMD64_DIGEST=$(shell $(COMMAND) run skopeo:latest --override-os linux inspect --creds $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) docker://$(MQ_IMAGE_ADVANCEDSERVER_AMD64) | jq -r .Digest))
|
||||
$(eval MQ_IMAGE_ADVANCEDSERVER_S390X_DIGEST=$(shell $(COMMAND) run skopeo:latest --override-os linux inspect --creds $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) docker://$(MQ_IMAGE_ADVANCEDSERVER_S390X) | jq -r .Digest))
|
||||
$(info $(shell printf "** Determined the built $(MQ_IMAGE_DEVSERVER_AMD64) has a digest of $(MQ_IMAGE_DEVSERVER_AMD64_DIGEST)**"$(END)))
|
||||
$(info $(shell printf "** Determined the built $(MQ_IMAGE_DEVSERVER_S390X) has a digest of $(MQ_IMAGE_DEVSERVER_S390X_DIGEST)**"$(END)))
|
||||
$(info $(shell printf "** Determined the built $(MQ_IMAGE_ADVANCEDSERVER_AMD64) has a digest of $(MQ_IMAGE_ADVANCEDSERVER_AMD64_DIGEST)**"$(END)))
|
||||
$(info $(shell printf "** Determined the built $(MQ_IMAGE_ADVANCEDSERVER_S390X) has a digest of $(MQ_IMAGE_ADVANCEDSERVER_S390X_DIGEST)**"$(END)))
|
||||
$(info $(shell printf "** Calling script to create fat-manifest for $(MQ_IMAGE_DEVSERVER_MANIFEST)**"$(END)))
|
||||
echo $(shell ./travis-build-scripts/create-manifest-list.sh -r $(MQ_DELIVERY_REGISTRY_HOSTNAME) -n $(MQ_DELIVERY_REGISTRY_NAMESPACE) -i $(MQ_IMAGE_DEVSERVER) -t $(MQ_MANIFEST_TAG) -u $(MQ_ARCHIVE_REPOSITORY_USER) -p $(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -d "$(MQ_IMAGE_DEVSERVER_AMD64_DIGEST) $(MQ_IMAGE_DEVSERVER_S390X_DIGEST)" $(END))
|
||||
$(info $(shell printf "** Calling script to create fat-manifest for $(MQ_IMAGE_ADVANCEDSERVER_MANIFEST)**"$(END)))
|
||||
echo $(shell ./travis-build-scripts/create-manifest-list.sh -r $(MQ_DELIVERY_REGISTRY_HOSTNAME) -n $(MQ_DELIVERY_REGISTRY_NAMESPACE) -i $(MQ_IMAGE_ADVANCEDSERVER) -t $(MQ_MANIFEST_TAG) -u $(MQ_ARCHIVE_REPOSITORY_USER) -p $(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -d "$(MQ_IMAGE_ADVANCEDSERVER_AMD64_DIGEST) $(MQ_IMAGE_ADVANCEDSERVER_S390X_DIGEST)" $(END))
|
||||
|
||||
.PHONY: build-skopeo-container
|
||||
build-skopeo-container:
|
||||
$(COMMAND) images | grep -q "skopeo"; if [ $$? != 0 ]; then docker build -t skopeo:latest ./docker-builds/skopeo/; fi
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf ./coverage
|
||||
rm -rf ./build
|
||||
rm -rf ./deps
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
glide install --strip-vendor
|
||||
.PHONY: install-build-deps
|
||||
install-build-deps:
|
||||
ARCH=$(ARCH) ./install-build-deps.sh
|
||||
|
||||
.PHONY: install-credential-helper
|
||||
install-credential-helper:
|
||||
ifeq ($(ARCH),amd64)
|
||||
ARCH=$(ARCH) ./travis-build-scripts/install-credential-helper.sh
|
||||
endif
|
||||
|
||||
.PHONY: build-cov
|
||||
build-cov:
|
||||
@@ -348,7 +414,8 @@ lint: $(addsuffix /$(wildcard *.go), $(GO_PKG_DIRS))
|
||||
golint -set_exit_status $(sort $(dir $(wildcard $(addsuffix /*/*.go, $(GO_PKG_DIRS)))))
|
||||
|
||||
.PHONY: gosec
|
||||
gosec: $(info $(SPACER)$(shell printf "Running gosec test"$(END)))
|
||||
gosec:
|
||||
$(info $(SPACER)$(shell printf "Running gosec test"$(END)))
|
||||
@gosec -fmt=json -out=gosec_results.json cmd/... internal/... 2> /dev/null ;\
|
||||
cat "gosec_results.json" ;\
|
||||
cat gosec_results.json | grep HIGH | grep severity > /dev/null ;\
|
||||
|
||||
12652
NOTICES.txt
12652
NOTICES.txt
File diff suppressed because it is too large
Load Diff
@@ -44,12 +44,11 @@ For issues relating specifically to the container image or Helm chart, please us
|
||||
The Dockerfiles and associated code and scripts are licensed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
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](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`
|
||||
- [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BMKG5H) (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-BMJJBM) (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.
|
||||
|
||||
Note: The IBM MQ Advanced for Developers license does not permit further distribution and the terms restrict usage to a developer machine.
|
||||
|
||||
## Copyright
|
||||
|
||||
© Copyright IBM Corporation 2015, 2019
|
||||
© Copyright IBM Corporation 2015, 2020
|
||||
|
||||
@@ -1,23 +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.
|
||||
|
||||
# Fedora includes more recent versions of buildah (need buildah V1.7 to get
|
||||
# multi-stage builds to work properly)
|
||||
FROM docker.io/fedora:29
|
||||
RUN yum install -y buildah
|
||||
COPY build.sh /usr/local/bin/build
|
||||
RUN chmod +x /usr/local/bin/build
|
||||
ENV STORAGE_DRIVER=vfs
|
||||
ENV BUILDAH_ISOLATION=chroot
|
||||
ENTRYPOINT ["build"]
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Build a container image from a Dockerfile using Buildah
|
||||
# If the Docker socket is available, the image will be pushed to Docker once built.
|
||||
|
||||
readonly IMAGE=$1:$2
|
||||
shift
|
||||
shift
|
||||
readonly SRC="/src"
|
||||
readonly OCI_DIR="/var/oci"
|
||||
|
||||
echo "****************************************"
|
||||
echo " Inside the Buildah container"
|
||||
echo "****************************************"
|
||||
set -ex
|
||||
# Build using the supplied options. Always pass the source directory in, and
|
||||
# use it as the build context
|
||||
buildah build-using-dockerfile --tag ${IMAGE} --volume /src:/src "$@" /src
|
||||
|
||||
if [ -e ${OCI_DIR} ]; then
|
||||
buildah push ${IMAGE} oci-archive:${OCI_DIR}/${IMAGE}
|
||||
fi
|
||||
|
||||
if [ -e /var/run/docker.sock ]; then
|
||||
buildah push ${IMAGE} docker-daemon:${IMAGE}
|
||||
fi
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Build and run a container image with Buildah installed
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 imageName imageTag buildah-options"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
readonly SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )"
|
||||
readonly DIR=${SCRIPT_DIR}/..
|
||||
readonly BUILDAH_IMAGE=mq-buildah
|
||||
RUN_OPTS="--volume ${DIR}:/src --cap-add SYS_ADMIN --rm --interactive --tty"
|
||||
CMD="docker"
|
||||
|
||||
# If Docker is installed, then map the Docker socket into the container, to
|
||||
# allow buildah to push the resulting image into Docker's image store
|
||||
# WARNING: This means that the buildah container can do anything the "docker"
|
||||
# can do.
|
||||
command -v docker
|
||||
if [[ $? == 0 && -e /var/run/docker.sock ]]; then
|
||||
RUN_OPTS="${RUN_OPTS} --volume /var/run/docker.sock:/var/run/docker.sock"
|
||||
fi
|
||||
|
||||
command -v podman
|
||||
if [[ $? -eq 0 ]]; then
|
||||
CMD="podman"
|
||||
OCI_DIR="/tmp/mq-buildah"
|
||||
mkdir -p ${OCI_DIR}
|
||||
RUN_OPTS="${RUN_OPTS} --volume ${OCI_DIR}:/var/oci"
|
||||
echo "Image archives will be written to ${OCI_DIR}"
|
||||
fi
|
||||
|
||||
${CMD} build --tag ${BUILDAH_IMAGE} --file ${SCRIPT_DIR}/Dockerfile ${SCRIPT_DIR}
|
||||
set -x
|
||||
${CMD} run ${RUN_OPTS} ${BUILDAH_IMAGE} "$@"
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/name"
|
||||
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||
)
|
||||
|
||||
func queueManagerHealthy() (bool, error) {
|
||||
@@ -36,11 +36,11 @@ func queueManagerHealthy() (bool, error) {
|
||||
cmd := exec.Command("dspmq", "-n", "-m", name)
|
||||
// Run the command and wait for completion
|
||||
out, err := cmd.CombinedOutput()
|
||||
fmt.Printf("%s", out)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, err
|
||||
}
|
||||
fmt.Printf("%s", out)
|
||||
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/name"
|
||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
© Copyright IBM Corporation 2018, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,10 @@ import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"github.com/ibm-messaging/mq-container/internal/containerruntimelogger"
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
||||
"github.com/ibm-messaging/mq-container/internal/name"
|
||||
"github.com/ibm-messaging/mq-container/internal/htpasswd"
|
||||
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||
)
|
||||
|
||||
var log *logger.Logger
|
||||
@@ -43,7 +42,7 @@ func setPassword(user string, password string) error {
|
||||
if err != nil {
|
||||
log.Errorf("Error closing password stdin: %v", err)
|
||||
}
|
||||
out, _, err := command.RunCmd(cmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
// Include the command output in the error
|
||||
return fmt.Errorf("%v: %v", err.Error(), out)
|
||||
@@ -90,11 +89,6 @@ func configureLogger() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureWeb(qmName string) error {
|
||||
out := "/etc/mqm/web/installations/Installation1/angular.persistence/admin.json"
|
||||
return mqtemplate.ProcessTemplateFile("/etc/mqm/admin.json.tpl", out, map[string]string{"QueueManagerName": qmName}, log)
|
||||
}
|
||||
|
||||
func logTerminationf(format string, args ...interface{}) {
|
||||
logTermination(fmt.Sprintf(format, args...))
|
||||
}
|
||||
@@ -126,16 +120,23 @@ func doMain() error {
|
||||
}
|
||||
|
||||
adminPassword, set := os.LookupEnv("MQ_ADMIN_PASSWORD")
|
||||
if set {
|
||||
err = setPassword("admin", adminPassword)
|
||||
if !set {
|
||||
adminPassword = "passw0rd"
|
||||
err = os.Setenv("MQ_ADMIN_PASSWORD", adminPassword)
|
||||
if err != nil {
|
||||
logTerminationf("Error setting admin password: %v", err)
|
||||
logTerminationf("Error setting admin password variable: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = htpasswd.SetPassword("admin", adminPassword, false)
|
||||
if err != nil {
|
||||
logTerminationf("Error setting admin password: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
appPassword, set := os.LookupEnv("MQ_APP_PASSWORD")
|
||||
if set {
|
||||
err = setPassword("app", appPassword)
|
||||
err = htpasswd.SetPassword("app", appPassword, false)
|
||||
if err != nil {
|
||||
logTerminationf("Error setting app password: %v", err)
|
||||
return err
|
||||
@@ -148,18 +149,6 @@ func doMain() error {
|
||||
return err
|
||||
}
|
||||
|
||||
name, err := name.GetQueueManagerName()
|
||||
if err != nil {
|
||||
logTerminationf("Error getting queue manager name: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = configureWeb(name)
|
||||
if err != nil {
|
||||
logTermination("Error configuring admin.json")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -172,7 +161,7 @@ func main() {
|
||||
} else {
|
||||
// Replace this process with runmqserver
|
||||
// #nosec G204
|
||||
err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-dev"}, os.Environ())
|
||||
err = syscall.Exec("/usr/local/bin/runmqserver", []string{"runmqserver", "-nologruntime", "-dev"}, os.Environ())
|
||||
if err != nil {
|
||||
log.Errorf("Error replacing this process with runmqserver: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -17,14 +17,10 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
)
|
||||
|
||||
func createVolume(dataPath string) error {
|
||||
fi, err := os.Stat(dataPath)
|
||||
_, err := os.Stat(dataPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// #nosec G301
|
||||
@@ -36,25 +32,5 @@ func createVolume(dataPath string) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fi, err = os.Stat(dataPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sys := fi.Sys()
|
||||
if sys != nil && runtime.GOOS == "linux" {
|
||||
stat := sys.(*syscall.Stat_t)
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("mqm user is %v (%v)", mqmUID, mqmGID)
|
||||
if int(stat.Uid) != mqmUID || int(stat.Gid) != mqmGID {
|
||||
err = os.Chown(dataPath, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
log.Printf("Error: Unable to change ownership of %v", dataPath)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -23,12 +23,13 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/internal/mqini"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/mqini"
|
||||
)
|
||||
|
||||
// var debug = false
|
||||
@@ -60,8 +61,25 @@ func getLogFormat() string {
|
||||
return os.Getenv("LOG_FORMAT")
|
||||
}
|
||||
|
||||
func formatSimple(datetime string, message string) string {
|
||||
return fmt.Sprintf("%v %v\n", datetime, message)
|
||||
// formatBasic formats a log message parsed from JSON, as "basic" text
|
||||
func formatBasic(obj map[string]interface{}) string {
|
||||
// Emulate the MQ "MessageDetail=Extended" option, by appending inserts to the message
|
||||
// This is important for certain messages, where key details are only available in the extended message content
|
||||
inserts := make([]string, 0)
|
||||
for k, v := range obj {
|
||||
if strings.HasPrefix(k, "ibm_commentInsert") {
|
||||
inserts = append(inserts, fmt.Sprintf("%s(%v)", strings.Replace(k, "ibm_comment", "Comment", 1), obj[k]))
|
||||
} else if strings.HasPrefix(k, "ibm_arithInsert") {
|
||||
if v.(float64) != 0 {
|
||||
inserts = append(inserts, fmt.Sprintf("%s(%v)", strings.Replace(k, "ibm_arith", "Arith", 1), obj[k]))
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(inserts)
|
||||
if len(inserts) > 0 {
|
||||
return fmt.Sprintf("%s %s [%v]\n", obj["ibm_datetime"], obj["message"], strings.Join(inserts, ", "))
|
||||
}
|
||||
return fmt.Sprintf("%s %s\n", obj["ibm_datetime"], obj["message"])
|
||||
}
|
||||
|
||||
// mirrorSystemErrorLogs starts a goroutine to mirror the contents of the MQ system error logs
|
||||
@@ -126,7 +144,8 @@ func configureLogger(name string) (mirrorFunc, error) {
|
||||
if err != nil {
|
||||
log.Printf("Failed to unmarshall JSON - %v", err)
|
||||
} else {
|
||||
fmt.Printf(formatSimple(obj["ibm_datetime"].(string), obj["message"].(string)))
|
||||
fmt.Printf(formatBasic(obj))
|
||||
// fmt.Printf(formatSimple(obj["ibm_datetime"].(string), obj["message"].(string)))
|
||||
}
|
||||
return true
|
||||
}, nil
|
||||
@@ -154,41 +173,43 @@ func filterQMLogMessage(obj map[string]interface{}) bool {
|
||||
}
|
||||
|
||||
func logDiagnostics() {
|
||||
log.Debug("--- Start Diagnostics ---")
|
||||
if getDebug() {
|
||||
log.Debug("--- Start Diagnostics ---")
|
||||
|
||||
// show the directory ownership/permissions
|
||||
// #nosec G104
|
||||
out, _, _ := command.Run("ls", "-l", "/mnt/")
|
||||
log.Debugf("/mnt/:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm")
|
||||
log.Debugf("/mnt/mqm:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm/data")
|
||||
log.Debugf("/mnt/mqm/data:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-log/log")
|
||||
log.Debugf("/mnt/mqm-log/log:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-data/qmgrs")
|
||||
log.Debugf("/mnt/mqm-data/qmgrs:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/var/mqm")
|
||||
log.Debugf("/var/mqm:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/var/mqm/errors")
|
||||
log.Debugf("/var/mqm/errors:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/etc/mqm")
|
||||
log.Debugf("/etc/mqm:\n%s", out)
|
||||
// show the directory ownership/permissions
|
||||
// #nosec G104
|
||||
out, _, _ := command.Run("ls", "-l", "/mnt/")
|
||||
log.Debugf("/mnt/:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm")
|
||||
log.Debugf("/mnt/mqm:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm/data")
|
||||
log.Debugf("/mnt/mqm/data:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-log/log")
|
||||
log.Debugf("/mnt/mqm-log/log:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-data/qmgrs")
|
||||
log.Debugf("/mnt/mqm-data/qmgrs:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/var/mqm")
|
||||
log.Debugf("/var/mqm:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/var/mqm/errors")
|
||||
log.Debugf("/var/mqm/errors:\n%s", out)
|
||||
// #nosec G104
|
||||
out, _, _ = command.Run("ls", "-l", "/etc/mqm")
|
||||
log.Debugf("/etc/mqm:\n%s", out)
|
||||
|
||||
// Print out summary of any FDCs
|
||||
// #nosec G204
|
||||
cmd := exec.Command("/opt/mqm/bin/ffstsummary")
|
||||
cmd.Dir = "/var/mqm/errors"
|
||||
// #nosec G104
|
||||
outB, _ := cmd.CombinedOutput()
|
||||
log.Debugf("ffstsummary:\n%s", string(outB))
|
||||
// Print out summary of any FDCs
|
||||
// #nosec G204
|
||||
cmd := exec.Command("/opt/mqm/bin/ffstsummary")
|
||||
cmd.Dir = "/var/mqm/errors"
|
||||
// #nosec G104
|
||||
outB, _ := cmd.CombinedOutput()
|
||||
log.Debugf("ffstsummary:\n%s", string(outB))
|
||||
|
||||
log.Debug("--- End Diagnostics ---")
|
||||
log.Debug("--- End Diagnostics ---")
|
||||
}
|
||||
}
|
||||
|
||||
55
cmd/runmqserver/logging_test.go
Normal file
55
cmd/runmqserver/logging_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var formatBasicTests = []struct {
|
||||
in []byte
|
||||
outContains string
|
||||
}{
|
||||
{
|
||||
[]byte("{\"ibm_datetime\":\"2020/06/24 00:00:00\",\"message\":\"Hello world\"}"),
|
||||
"Hello",
|
||||
},
|
||||
{
|
||||
[]byte("{\"ibm_datetime\":\"2020/06/24 00:00:00\",\"message\":\"Hello world\", \"ibm_commentInsert1\":\"foo\"}"),
|
||||
"CommentInsert1(foo)",
|
||||
},
|
||||
{
|
||||
[]byte("{\"ibm_datetime\":\"2020/06/24 00:00:00\",\"message\":\"Hello world\", \"ibm_arithInsert1\":1}"),
|
||||
"ArithInsert1(1)",
|
||||
},
|
||||
}
|
||||
|
||||
func TestFormatBasic(t *testing.T) {
|
||||
for i, table := range formatBasicTests {
|
||||
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
|
||||
var inObj map[string]interface{}
|
||||
json.Unmarshal(table.in, &inObj)
|
||||
t.Logf("Unmarshalled: %+v", inObj)
|
||||
out := formatBasic(inObj)
|
||||
if !strings.Contains(out, table.outContains) {
|
||||
t.Errorf("formatBasic() with input=%v - expected output to contain %v, got %v", string(table.in), table.outContains, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -24,17 +24,18 @@ import (
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/containerruntimelogger"
|
||||
"github.com/ibm-messaging/mq-container/internal/metrics"
|
||||
"github.com/ibm-messaging/mq-container/internal/name"
|
||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||
)
|
||||
|
||||
func doMain() error {
|
||||
var initFlag = flag.Bool("i", false, "initialize volume only, then exit")
|
||||
var infoFlag = flag.Bool("info", false, "Display debug info, then exit")
|
||||
var devFlag = flag.Bool("dev", false, "used when running this program from runmqdevserver to control log output")
|
||||
var noLogRuntimeFlag = flag.Bool("nologruntime", false, "used when running this program from another program, to control log output")
|
||||
var devFlag = flag.Bool("dev", false, "used when running this program from runmqdevserver to control how TLS is configured")
|
||||
flag.Parse()
|
||||
|
||||
name, nameErr := name.GetQueueManagerName()
|
||||
@@ -87,7 +88,7 @@ func doMain() error {
|
||||
// Enable diagnostic collecting on failure
|
||||
collectDiagOnFail = true
|
||||
|
||||
if *devFlag == false {
|
||||
if *noLogRuntimeFlag == false {
|
||||
err = containerruntimelogger.LogContainerDetails(log)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
@@ -111,12 +112,29 @@ func doMain() error {
|
||||
return err
|
||||
}
|
||||
|
||||
enableTraceCrtmqdir := os.Getenv("MQ_ENABLE_TRACE_CRTMQDIR")
|
||||
if enableTraceCrtmqdir == "true" || enableTraceCrtmqdir == "1" {
|
||||
err = startMQTrace()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = createDirStructure()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if enableTraceCrtmqdir == "true" || enableTraceCrtmqdir == "1" {
|
||||
err = endMQTrace()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If init flag is set, exit now
|
||||
if *initFlag {
|
||||
return nil
|
||||
@@ -125,29 +143,30 @@ func doMain() error {
|
||||
// Print out versioning information
|
||||
logVersionInfo()
|
||||
|
||||
keylabel, cmsDB, p12Trust, _, err := tls.ConfigureTLSKeystores(keyDir, trustDir, keyStoreDir)
|
||||
keyLabel, cmsKeystore, p12Truststore, err := tls.ConfigureTLSKeystores()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = configureTLS(keylabel, cmsDB, *devFlag)
|
||||
err = tls.ConfigureTLS(keyLabel, cmsKeystore, *devFlag, log)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = postInit(name, keylabel, p12Trust)
|
||||
err = postInit(name, keyLabel, p12Truststore)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
newQM, err := createQueueManager(name)
|
||||
newQM, err := createQueueManager(name, *devFlag)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
defer func() {
|
||||
log.Debug("Waiting for log mirroring to complete")
|
||||
@@ -174,13 +193,34 @@ func doMain() error {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
|
||||
enableTraceStrmqm := os.Getenv("MQ_ENABLE_TRACE_STRMQM")
|
||||
if enableTraceStrmqm == "true" || enableTraceStrmqm == "1" {
|
||||
err = startMQTrace()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// This is a developer image only change
|
||||
// This workaround should be removed and handled via <crtmqm -ii>, when inimerge is ready to handle stanza ordering
|
||||
if *devFlag {
|
||||
err = updateQMini(name)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = startQueueManager(name)
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
}
|
||||
if standby, _ := ready.IsRunningAsStandbyQM(name); !standby {
|
||||
err = configureQueueManager()
|
||||
|
||||
if enableTraceStrmqm == "true" || enableTraceStrmqm == "1" {
|
||||
err = endMQTrace()
|
||||
if err != nil {
|
||||
logTermination(err)
|
||||
return err
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2018
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
)
|
||||
|
||||
var test *bool
|
||||
|
||||
@@ -22,18 +22,23 @@ import (
|
||||
)
|
||||
|
||||
// postInit is run after /var/mqm is set up
|
||||
func postInit(name, keylabel string, p12Trust tls.KeyStoreData) error {
|
||||
func postInit(name, keyLabel string, p12Truststore tls.KeyStoreData) error {
|
||||
enableWebServer := os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER")
|
||||
if enableWebServer == "true" || enableWebServer == "1" {
|
||||
// Configure the web server (if enabled)
|
||||
keystore, err := configureWebServer(keylabel, p12Trust)
|
||||
webKeystore, err := configureWebServer(keyLabel, p12Truststore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If trust-store is empty, set reference to point to the keystore
|
||||
webTruststoreRef := "MQWebTrustStore"
|
||||
if len(p12Truststore.TrustedCerts) == 0 {
|
||||
webTruststoreRef = "MQWebKeyStore"
|
||||
}
|
||||
// Start the web server, in the background (if installed)
|
||||
// WARNING: No error handling or health checking available for the web server
|
||||
go func() {
|
||||
err = startWebServer(keystore, p12Trust.Password)
|
||||
err = startWebServer(webKeystore, p12Truststore.Password, webTruststoreRef)
|
||||
if err != nil {
|
||||
log.Printf("Error starting web server: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,12 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
@@ -32,18 +32,25 @@ import (
|
||||
|
||||
// createDirStructure creates the default MQ directory structure under /var/mqm
|
||||
func createDirStructure() error {
|
||||
out, _, err := command.Run("/opt/mqm/bin/crtmqdir", "-f", "-a")
|
||||
// log file diagnostics before and after crtmqdir if DEBUG=true
|
||||
logDiagnostics()
|
||||
out, rc, err := command.Run("/opt/mqm/bin/crtmqdir", "-f", "-a")
|
||||
if err != nil {
|
||||
log.Printf("Error creating directory structure: %v\n", string(out))
|
||||
return err
|
||||
if rc == 10 {
|
||||
log.Printf("Warning creating directory structure: %v\n", string(out))
|
||||
} else {
|
||||
log.Printf("Error creating directory structure: %v\n", string(out))
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Println("Created directory structure under /var/mqm")
|
||||
logDiagnostics()
|
||||
return nil
|
||||
}
|
||||
|
||||
// createQueueManager creates a queue manager, if it doesn't already exist.
|
||||
// It returns true if one was created (or a standby was created), or false if one already existed
|
||||
func createQueueManager(name string) (bool, error) {
|
||||
func createQueueManager(name string, devMode bool) (bool, error) {
|
||||
log.Printf("Creating queue manager %v", name)
|
||||
|
||||
// Run 'dspmqinf' to check if 'mqs.ini' configuration file exists
|
||||
@@ -66,7 +73,7 @@ func createQueueManager(name string) (bool, error) {
|
||||
_, err = os.Stat(filepath.Join(dataDir, "qm.ini"))
|
||||
if err != nil {
|
||||
// If 'qm.ini' is not found - run 'crtmqm' to create a new queue manager
|
||||
args := getCreateQueueManagerArgs(mounts, name)
|
||||
args := getCreateQueueManagerArgs(mounts, name, devMode)
|
||||
out, rc, err := command.Run("crtmqm", args...)
|
||||
if err != nil {
|
||||
log.Printf("Error %v creating queue manager: %v", rc, string(out))
|
||||
@@ -116,74 +123,20 @@ func startQueueManager(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureQueueManager() error {
|
||||
const configDir string = "/etc/mqm"
|
||||
files, err := ioutil.ReadDir(configDir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
if strings.HasSuffix(file.Name(), ".mqsc") {
|
||||
abs := filepath.Join(configDir, file.Name())
|
||||
// #nosec G204
|
||||
verify := exec.Command("runmqsc", "-v", "-e")
|
||||
// #nosec G204 - command is fixed, no injection vector
|
||||
cmd := exec.Command("runmqsc")
|
||||
// Read mqsc file into variable
|
||||
// #nosec G304 - filename variable is derived from contents of 'configDir' which is a defined constant
|
||||
mqsc, err := ioutil.ReadFile(abs)
|
||||
if err != nil {
|
||||
log.Printf("Error reading file %v: %v", abs, err)
|
||||
continue
|
||||
}
|
||||
// Write mqsc to buffer
|
||||
var buffer bytes.Buffer
|
||||
_, err = buffer.Write(mqsc)
|
||||
if err != nil {
|
||||
log.Printf("Error writing MQSC file %v to buffer: %v", abs, err)
|
||||
continue
|
||||
}
|
||||
verifyBuffer := buffer
|
||||
|
||||
// Buffer mqsc to stdin of runmqsc
|
||||
cmd.Stdin = &buffer
|
||||
verify.Stdin = &verifyBuffer
|
||||
|
||||
// Verify the MQSC commands
|
||||
out, err := verify.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Errorf("Error verifying MQSC file %v (%v):\n\t%v", file.Name(), err, formatMQSCOutput(string(out)))
|
||||
return fmt.Errorf("Error verifying MQSC file %v (%v):\n\t%v", file.Name(), err, formatMQSCOutput(string(out)))
|
||||
}
|
||||
|
||||
// Run runmqsc command
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Errorf("Error running MQSC file %v (%v):\n\t%v", file.Name(), err, formatMQSCOutput(string(out)))
|
||||
continue
|
||||
} else {
|
||||
// Print the runmqsc output, adding tab characters to make it more readable as part of the log
|
||||
log.Printf("Output for \"runmqsc\" with %v:\n\t%v", abs, formatMQSCOutput(string(out)))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopQueueManager(name string) error {
|
||||
log.Println("Stopping queue manager")
|
||||
qmGracePeriod := os.Getenv("MQ_GRACE_PERIOD")
|
||||
isStandby, err := ready.IsRunningAsStandbyQM(name)
|
||||
if err != nil {
|
||||
log.Printf("Error getting status for queue manager %v: ", name, err.Error())
|
||||
log.Printf("Error getting status for queue manager %v: %v", name, err.Error())
|
||||
return err
|
||||
}
|
||||
args := []string{"-w", "-r", name}
|
||||
args := []string{"-w", "-r", "-tp", qmGracePeriod, name}
|
||||
if os.Getenv("MQ_MULTI_INSTANCE") == "true" {
|
||||
if isStandby {
|
||||
args = []string{"-x", name}
|
||||
} else {
|
||||
args = []string{"-s", "-w", "-r", name}
|
||||
args = []string{"-s", "-w", "-r", "-tp", qmGracePeriod, name}
|
||||
}
|
||||
}
|
||||
out, rc, err := command.Run("endmqm", args...)
|
||||
@@ -199,6 +152,28 @@ func stopQueueManager(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func startMQTrace() error {
|
||||
log.Println("Starting MQ trace")
|
||||
out, rc, err := command.Run("strmqtrc")
|
||||
if err != nil {
|
||||
log.Printf("Error %v starting trace: %v", rc, string(out))
|
||||
return err
|
||||
}
|
||||
log.Println("Started MQ trace")
|
||||
return nil
|
||||
}
|
||||
|
||||
func endMQTrace() error {
|
||||
log.Println("Ending MQ Trace")
|
||||
out, rc, err := command.Run("endmqtrc")
|
||||
if err != nil {
|
||||
log.Printf("Error %v ending trace: %v", rc, string(out))
|
||||
return err
|
||||
}
|
||||
log.Println("Ended MQ trace")
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatMQSCOutput(out string) string {
|
||||
// redact sensitive information
|
||||
out, _ = mqscredact.Redact(out)
|
||||
@@ -227,8 +202,11 @@ func getQueueManagerDataDir(mounts map[string]string, name string) string {
|
||||
return dataDir
|
||||
}
|
||||
|
||||
func getCreateQueueManagerArgs(mounts map[string]string, name string) []string {
|
||||
args := []string{"-q", "-p", "1414"}
|
||||
func getCreateQueueManagerArgs(mounts map[string]string, name string, devMode bool) []string {
|
||||
args := []string{"-ii", "/etc/mqm/", "-ic", "/etc/mqm/", "-q", "-p", "1414"}
|
||||
if devMode {
|
||||
args = append(args, "-oa", "user")
|
||||
}
|
||||
if _, ok := mounts["/mnt/mqm-log"]; ok {
|
||||
args = append(args, "-ld", "/mnt/mqm-log/log")
|
||||
}
|
||||
@@ -247,3 +225,48 @@ func getCreateStandbyQueueManagerArgs(name string) []string {
|
||||
args = append(args, "-v", fmt.Sprintf("DataPath=/mnt/mqm-data/qmgrs/%v", name))
|
||||
return args
|
||||
}
|
||||
|
||||
// updateQMini removes the original ServicecCmponent stanza so we can add a new one
|
||||
func updateQMini(qmname string) error {
|
||||
|
||||
val, set := os.LookupEnv("MQ_CONNAUTH_USE_HTP")
|
||||
if !set {
|
||||
//htpasswd mode not enabled.
|
||||
return nil
|
||||
}
|
||||
bval, err := strconv.ParseBool(strings.ToLower(val))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bval == false {
|
||||
//htpasswd mode not enabled.
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("Removing existing ServiceComponent configuration")
|
||||
|
||||
mounts, err := containerruntime.GetMounts()
|
||||
if err != nil {
|
||||
log.Printf("Error getting mounts for queue manager")
|
||||
return err
|
||||
}
|
||||
dataDir := getQueueManagerDataDir(mounts, qmname)
|
||||
qmgrDir := filepath.Join(dataDir, "qm.ini")
|
||||
//read the initial version.
|
||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
||||
iniFileBytes, err := ioutil.ReadFile(qmgrDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
qminiConfigStr := string(iniFileBytes)
|
||||
if strings.Contains(qminiConfigStr, "ServiceComponent:") {
|
||||
var re = regexp.MustCompile(`(?m)^.*ServiceComponent.*$\s^.*Service.*$\s^.*Name.*$\s^.*Module.*$\s^.*ComponentDataSize.*$`)
|
||||
curFile := re.ReplaceAllString(qminiConfigStr, "")
|
||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
||||
err := ioutil.WriteFile(qmgrDir, []byte(curFile), 0660)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,166 +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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"github.com/ibm-messaging/mq-container/internal/keystore"
|
||||
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||
)
|
||||
|
||||
// Location to store the keystores
|
||||
const keyStoreDir = "/run/runmqserver/tls/"
|
||||
|
||||
// KeyDir is the location of the certificate keys to import
|
||||
const keyDir = "/etc/mqm/pki/keys"
|
||||
|
||||
// TrustDir is the location of the Certifates to add
|
||||
const trustDir = "/etc/mqm/pki/trust"
|
||||
|
||||
// configureWebTLS configures TLS for Web Console
|
||||
func configureWebTLS(label string) error {
|
||||
// Return immediately if we have no certificate to use as identity
|
||||
if label == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
webConfigDir := "/etc/mqm/web/installations/Installation1/servers/mqweb"
|
||||
tls := "tls.xml"
|
||||
|
||||
tlsConfig := filepath.Join(webConfigDir, tls)
|
||||
newTLSConfig := filepath.Join(webConfigDir, tls+".tpl")
|
||||
err := os.Remove(tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not delete file %s: %v", tlsConfig, err)
|
||||
}
|
||||
// we symlink here to prevent issues on restart
|
||||
err = os.Symlink(newTLSConfig, tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not create symlink %s->%s: %v", newTLSConfig, tlsConfig, err)
|
||||
}
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not find mqm user or group: %v", err)
|
||||
}
|
||||
err = os.Chown(tlsConfig, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could change ownership of %s to mqm: %v", tlsConfig, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// configureTLSDev configures TLS for developer defaults
|
||||
func configureTLSDev() error {
|
||||
const mqsc string = "/etc/mqm/20-dev-tls.mqsc"
|
||||
const mqscTemplate string = mqsc + ".tpl"
|
||||
const sslCipherSpec string = "TLS_RSA_WITH_AES_128_CBC_SHA256"
|
||||
|
||||
if os.Getenv("MQ_DEV") == "true" {
|
||||
err := mqtemplate.ProcessTemplateFile(mqscTemplate, mqsc, map[string]string{
|
||||
"SSLCipherSpec": sslCipherSpec,
|
||||
}, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, err := os.Stat(mqsc)
|
||||
if !os.IsNotExist(err) {
|
||||
err = os.Remove(mqsc)
|
||||
if err != nil {
|
||||
log.Errorf("Error removing file %s: %v", mqsc, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// configureTLS configures TLS for queue manager
|
||||
func configureTLS(certLabel string, cmsKeystore tls.KeyStoreData, devmode bool) error {
|
||||
log.Debug("Configuring TLS")
|
||||
|
||||
const mqsc string = "/etc/mqm/15-tls.mqsc"
|
||||
const mqscTemplate string = mqsc + ".tpl"
|
||||
|
||||
err := mqtemplate.ProcessTemplateFile(mqscTemplate, mqsc, map[string]string{
|
||||
"SSLKeyR": strings.TrimSuffix(cmsKeystore.Keystore.Filename, ".kdb"),
|
||||
"CertificateLabel": certLabel,
|
||||
}, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if devmode && certLabel != "" {
|
||||
err = configureTLSDev()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// configureSSOTLS configures MQ Console TLS for Single Sign-On
|
||||
func configureSSOTLS(p12TrustStore tls.KeyStoreData) (string, error) {
|
||||
// TODO find way to supply this
|
||||
// Override the webstore variables to hard coded defaults
|
||||
webKeyStoreName := tls.IntegrationDefaultLabel + ".p12"
|
||||
|
||||
// Check keystore exists
|
||||
ks := filepath.Join(keyStoreDir, webKeyStoreName)
|
||||
_, err := os.Stat(ks)
|
||||
// Now we know if the file exists let's check whether we should have it or not.
|
||||
// Check if we're being told to generate the certificate
|
||||
genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME")
|
||||
if genHostName != "" {
|
||||
// We've got to generate the certificate with the hostname given
|
||||
if err == nil {
|
||||
log.Printf("Replacing existing keystore %s - generating new certificate", ks)
|
||||
}
|
||||
// Keystore doesn't exist so create it and populate a certificate
|
||||
newKS := keystore.NewPKCS12KeyStore(ks, p12TrustStore.Password)
|
||||
err = newKS.Create()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to create keystore %s: %v", ks, err)
|
||||
}
|
||||
|
||||
err = newKS.CreateSelfSignedCertificate("default", fmt.Sprintf("CN=%s", genHostName), genHostName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to generate certificate in keystore %s with DN of 'CN=%s': %v", ks, genHostName, err)
|
||||
}
|
||||
} else {
|
||||
// Keystore should already exist
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to find existing keystore %s: %v", ks, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check truststore exists
|
||||
_, err = os.Stat(p12TrustStore.Keystore.Filename)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to find existing truststore %s: %v", p12TrustStore.Keystore.Filename, err)
|
||||
}
|
||||
|
||||
return webKeyStoreName, nil
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
© Copyright IBM Corporation 2018, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -19,19 +19,15 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"github.com/ibm-messaging/mq-container/internal/copy"
|
||||
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||
)
|
||||
|
||||
func startWebServer(keystore, keystorepw string) error {
|
||||
func startWebServer(webKeystore, webkeystorePW, webTruststoreRef string) error {
|
||||
_, err := os.Stat("/opt/mqm/bin/strmqweb")
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
log.Debug("Skipping web server, because it's not installed")
|
||||
@@ -50,29 +46,13 @@ func startWebServer(keystore, keystorepw string) error {
|
||||
}
|
||||
|
||||
// TLS enabled
|
||||
if keystore != "" {
|
||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+keystore)
|
||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+keystorepw)
|
||||
if webKeystore != "" {
|
||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+webKeystore)
|
||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+webkeystorePW)
|
||||
cmd.Env = append(cmd.Env, "AMQ_WEBTRUSTSTOREREF="+webTruststoreRef)
|
||||
}
|
||||
|
||||
uid, gid, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentUID, err := strconv.Atoi(u.Uid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error converting UID to string: %v", err)
|
||||
}
|
||||
// Add credentials to run as 'mqm', only if we aren't already 'mqm'
|
||||
if currentUID != uid {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||
}
|
||||
out, rc, err := command.RunCmd(cmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
rc := cmd.ProcessState.ExitCode()
|
||||
if err != nil {
|
||||
log.Printf("Error %v starting web server: %v", rc, string(out))
|
||||
return err
|
||||
@@ -81,10 +61,9 @@ func startWebServer(keystore, keystorepw string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureSSO(p12TrustStore tls.KeyStoreData) (string, error) {
|
||||
func configureSSO(p12TrustStore tls.KeyStoreData, webKeystore string) (string, error) {
|
||||
// Ensure all required environment variables are set for SSO
|
||||
requiredEnvVars := []string{
|
||||
"MQ_WEB_ADMIN_USERS",
|
||||
"MQ_OIDC_CLIENT_ID",
|
||||
"MQ_OIDC_CLIENT_SECRET",
|
||||
"MQ_OIDC_UNIQUE_USER_IDENTIFIER",
|
||||
@@ -117,46 +96,49 @@ func configureSSO(p12TrustStore tls.KeyStoreData) (string, error) {
|
||||
}
|
||||
|
||||
// Configure SSO TLS
|
||||
return configureSSOTLS(p12TrustStore)
|
||||
return tls.ConfigureWebKeystore(p12TrustStore, webKeystore)
|
||||
}
|
||||
|
||||
func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, error) {
|
||||
var keystore string
|
||||
func configureWebServer(keyLabel string, p12Truststore tls.KeyStoreData) (string, error) {
|
||||
var webKeystore string
|
||||
|
||||
// Configure TLS for Web Console first if we have a certificate to use
|
||||
err := configureWebTLS(keyLabel)
|
||||
err := tls.ConfigureWebTLS(keyLabel)
|
||||
if err != nil {
|
||||
return keystore, err
|
||||
return "", err
|
||||
}
|
||||
if keyLabel != "" {
|
||||
keystore = keyLabel + ".p12"
|
||||
webKeystore = keyLabel + ".p12"
|
||||
}
|
||||
|
||||
// Configure Single-Sign-On for the web server (if enabled)
|
||||
enableSSO := os.Getenv("MQ_BETA_ENABLE_SSO")
|
||||
if enableSSO == "true" || enableSSO == "1" {
|
||||
keystore, err = configureSSO(p12Trust)
|
||||
webKeystore, err = configureSSO(p12Truststore, webKeystore)
|
||||
if err != nil {
|
||||
return keystore, err
|
||||
return "", err
|
||||
}
|
||||
} else if keyLabel == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") != "" {
|
||||
webKeystore, err = tls.ConfigureWebKeystore(p12Truststore, webKeystore)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = os.Stat("/opt/mqm/bin/strmqweb")
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return keystore, nil
|
||||
return "", nil
|
||||
}
|
||||
return keystore, err
|
||||
return "", err
|
||||
}
|
||||
const webConfigDir string = "/etc/mqm/web"
|
||||
_, err = os.Stat(webConfigDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return keystore, nil
|
||||
return "", nil
|
||||
}
|
||||
return keystore, err
|
||||
}
|
||||
uid, gid, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return keystore, err
|
||||
return "", err
|
||||
}
|
||||
const prefix string = "/etc/mqm/web"
|
||||
err = filepath.Walk(prefix, func(from string, info os.FileInfo, err error) error {
|
||||
@@ -194,11 +176,8 @@ func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = os.Chown(to, uid, gid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return keystore, err
|
||||
|
||||
return webKeystore, err
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2015, 2017
|
||||
# © Copyright IBM Corporation 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM mqadvanced
|
||||
RUN useradd alice -G mqm && \
|
||||
echo alice:passw0rd | chpasswd
|
||||
COPY *.mqsc /etc/mqm/
|
||||
FROM fedora:32
|
||||
RUN yum install skopeo -y -qq
|
||||
ENTRYPOINT [ "skopeo" ]
|
||||
@@ -4,26 +4,23 @@
|
||||
|
||||
You need to have the following tools installed:
|
||||
|
||||
* [Docker](https://www.docker.com/) V17.06.1 or later
|
||||
* [Docker](https://www.docker.com/) V17.06.1 or later, or [Podman](https://podman.io) V1.0 or later
|
||||
* [GNU make](https://www.gnu.org/software/make/)
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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. Run `make build-advancedserver`
|
||||
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.2.0_LINUX_X86-64_NOINST.tar.gz`) in the `downloads` directory
|
||||
3. Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
|
||||
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 MQ container build uses a Red Hat Universal Base Image, so you need the "MQ for Linux" RPM files.
|
||||
|
||||
You can build a different version of MQ by setting the `MQ_VERSION` environment variable, for example:
|
||||
|
||||
```bash
|
||||
MQ_VERSION=9.1.0.0 make build-advancedserver
|
||||
```
|
||||
> **Warning**: Note that from MQ 9.2.X, the MQ container build uses a 'No-Install' MQ Package, available under `IBM MQ V9.2.x Continuous Delivery Release components eAssembly, part no. CJ7CNML`
|
||||
|
||||
If you have an MQ archive file with a different file name, you can specify a particular file (which must be in the `downloads` directory). You should also specify the MQ version, so that the resulting image is tagged correctly, for example:
|
||||
|
||||
@@ -32,15 +29,12 @@ MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
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).
|
||||
|
||||
## Building from a Red Hat Enterprise Linux host
|
||||
Red Hat Enterprise Linux (RHEL) offers a suite of container tools, including Buildah for building container images, and Podman for running containers. Buildah can accept input described in a [Dockerfile](https://docs.docker.com/engine/reference/builder/). This MQ sample uses a multi-stage build, which requires a recent version of Podman, which is not yet available in Red Hat Enterprise Linux V7. Therefore, if you are on a RHEL host, then the `build-devserver` and `build-advancedserver` targets are run using a more recent version of Buildah from inside a container.
|
||||
|
||||
The containerized build process on a RHEL host will write an OCI compliant archive file to `/tmp/mq-buildah`. If a version of Docker is installed on the host, it will also push the image into Docker's internal image registry.
|
||||
|
||||
## Installed components
|
||||
|
||||
This image includes the core MQ server, Java, language packs, GSKit, and web server. This can be configured by setting the `MQ_PACKAGES` argument to `make`.
|
||||
This image includes the core MQ server, Java, language packs, GSKit, and web server. This is configured in the `Generate MQ package in INSTALLATION_DIR` section [here](../install-mq.sh), with the configured options being picked up at build time.
|
||||
|
||||
@@ -9,14 +9,12 @@ The MQ Developer Defaults supports some customization options, these are all con
|
||||
* **MQ_DEV** - Set this to `false` to stop the default objects being created.
|
||||
* **MQ_ADMIN_PASSWORD** - Changes the password of the `admin` user. Must be at least 8 characters long.
|
||||
* **MQ_APP_PASSWORD** - Changes the password of the app user. If set, this will cause the `DEV.APP.SVRCONN` channel to become secured and only allow connections that supply a valid userid and password. Must be at least 8 characters long.
|
||||
* **MQ_TLS_KEYSTORE** - **DEPRECATED**. See section `Supplying TLS certificates` in [usage document](usage.md). Allows you to supply the location of a PKCS#12 keystore containing a single certificate which you want to use in both the web console and the queue manager. Requires `MQ_TLS_PASSPHRASE`. When enabled the channels created will be secured using the `TLS_RSA_WITH_AES_128_CBC_SHA256` CipherSpec. *Note*: you will need to make the keystore available inside your container, this can be done by mounting a volume to your container.
|
||||
* **MQ_TLS_PASSPHRASE** - **DEPRECATED**. See section `Supplying TLS certificates` in [usage document](usage.md). Passphrase for the keystore referenced in `MQ_TLS_KEYSTORE`.
|
||||
|
||||
## Details of the default configuration
|
||||
|
||||
The following users are created:
|
||||
|
||||
* User **admin** for administration (in the `mqm` group). Default password is **passw0rd**.
|
||||
* User **admin** for administration. Default password is **passw0rd**.
|
||||
* User **app** for messaging (in a group called `mqclient`). No password by default.
|
||||
|
||||
Users in `mqclient` group have been given access connect to all queues and topics starting with `DEV.**` and have `put`, `get`, `pub`, `sub`, `browse` and `inq` permissions.
|
||||
@@ -34,11 +32,6 @@ 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.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
|
||||
|
||||
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.
|
||||
@@ -50,6 +43,6 @@ If you choose to accept the security warning, you will be presented with the log
|
||||
* **User:** admin
|
||||
* **Password:** passw0rd
|
||||
|
||||
If you wish to change the password for the admin user, this can be done using the `MQ_ADMIN_PASSWORD` environment variable. If you supply a PKCS#12 keystore using the `MQ_TLS_KEYSTORE` environment variable, then the web console will be configured to use the certificate inside the keystore for HTTPS operations.
|
||||
If you wish to change the password for the admin user, this can be done using the `MQ_ADMIN_PASSWORD` environment variable.
|
||||
|
||||
If you do not wish the web console to run, you can disable it by setting the environment variable `MQ_ENABLE_EMBEDDED_WEB_SERVER` to `false`.
|
||||
|
||||
29
docs/pluggable-connauth.md
Normal file
29
docs/pluggable-connauth.md
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
### Queue Manager Connection Authentication using a htpasswd file
|
||||
|
||||
This pluggable authentication mode is to allow developers using the mq-container developer image to define users and their credentials into a .htpasswd file. This is in addition to the existing methods of MQ Connection Authentication (`CONNAUTH`) using Operating System or LDAP users.
|
||||
|
||||
**Please note:**
|
||||
1. This new feature is enabled only when environment variable `--env MQ_CONNAUTH_USE_HTP=true` is set while creating a container.
|
||||
2. When enabled, the `AuthType` value of the ConnectionAuthentication (`CONNAUTH`) is ignored and htpasswd mode is used. However, the MQ authority records created using (`SETMQAUT` or `AUTHREC`) will be in effect while using the htpasswd mode.
|
||||
3. Channel Authentication records (`CHLAUTH`) will be in effect while using the htpasswd mode.
|
||||
4. Passwords should be encrypted using bcrypt (golang.org/x/crypto/bcrypt).
|
||||
5. This is developer only feature and not recommended for use in Production.
|
||||
|
||||
### Preparing htpasswd file
|
||||
|
||||
1. A default `mq.htpasswd` file is provided and placed under /etc/mqm/ directory inside the container.
|
||||
2. You can set the password for user `admin` by setting the environment variable `MQ_ADMIN_PASSWORD`.
|
||||
3. You can add user `app` into mq.htpasswd file by setting the environment variable `MQ_APP_PASSWORD`. This user `app` can be used to access `DEV.*` objects of the queue manager.
|
||||
|
||||
#### Next Steps:
|
||||
|
||||
Use an administrative tool or your application to connect to queue manager using the credentials defined in the mq.htpasswd file.
|
||||
|
||||
**Please note**: When an authentication request is made with a userid that is not defined in the `mq.htpasswd` file, then the authentication process is delegated to queue manager to handle. This will then use `IDPWOS` or `LDAP` modes for further processing.
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
A log file named `amqpasdev.log` is generated under `/var/mqm/errors` directory path of the container. This file will contain all the failed connection authentication requests.
|
||||
|
||||
**Please note**: This log file is based on circular logging and the maximum size is restricted to 1MB.
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
### User
|
||||
|
||||
The MQ server image is run using the "mqm" user, with a fixed UID and GID of 888.
|
||||
The MQ server image is run using with UID 1001, though this can be any UID, with a fixed GID of 0 (root).
|
||||
|
||||
### Capabilities
|
||||
|
||||
@@ -16,7 +16,7 @@ docker run \
|
||||
--env LICENSE=accept \
|
||||
--env MQ_QMGR_NAME=QM1 \
|
||||
--detach \
|
||||
mqadvanced-server:9.1.3.0-amd64
|
||||
ibm-mqadvanced-server:9.2.0.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:
|
||||
@@ -31,9 +31,5 @@ docker run \
|
||||
--env LICENSE=accept \
|
||||
--env MQ_QMGR_NAME=QM1 \
|
||||
--detach \
|
||||
mqadvanced-server-dev:9.1.3.0-amd64
|
||||
ibm-mqadvanced-server-dev:9.2.0.0-amd64
|
||||
```
|
||||
|
||||
### SELinux
|
||||
|
||||
The SELinux label "spc_t" (super-privileged container) is needed to run the MQ container on a host with SELinux enabled. This is due to a current limitation in how MQ data is stored on volumes, which violates the usual policy applied when using the standard "container_t" label.
|
||||
|
||||
@@ -14,29 +14,30 @@ There are two main sets of tests:
|
||||
2. Docker tests, which test a complete Docker image, using the Docker API
|
||||
|
||||
### Running the Docker tests
|
||||
The Docker tests can be run locally on a machine with Docker. For example:
|
||||
|
||||
The Docker tests can be run locally on a machine with Docker. For example:
|
||||
|
||||
```
|
||||
make test-devserver
|
||||
make test-advancedserver
|
||||
make devserver
|
||||
make advancedserver
|
||||
```
|
||||
|
||||
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.3.0-amd64 make test-advancedserver
|
||||
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:9.2.0.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:
|
||||
|
||||
```
|
||||
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.3.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 `ibm-mqadvanced-server:9.2.0.0-amd64`:
|
||||
|
||||
```
|
||||
MQ_VERSION=9.1.3.0 make test-advancedserver
|
||||
MQ_VERSION=9.2.0.0 make test-advancedserver
|
||||
```
|
||||
|
||||
### Running the Docker tests with code coverage
|
||||
@@ -48,12 +49,3 @@ make test-advancedserver-cover
|
||||
```
|
||||
|
||||
In order to generate code coverage metrics from the Docker tests, the build step creates a new Docker image with an instrumented version of the code. Each test is then run individually, producing a coverage report each under `test/docker/coverage/`. These individual reports are then combined. The combined report is written to the `coverage` directory.
|
||||
|
||||
|
||||
### Running the Kubernetes tests
|
||||
|
||||
For the Kubernetes tests, you need to have built the Docker image, and pushed it to the registry used by your Kubernetes cluster. Most of the configuration used by the tests is picked up from your `kubectl` configuration, but you will typically need to specify the image details. For example:
|
||||
|
||||
```bash
|
||||
MQ_IMAGE=mycluster.icp:8500/default/mq-devserver make test-kubernetes-devserver
|
||||
```
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
In order to use the image, it is necessary to accept the terms of the IBM MQ license. This is achieved by specifying the environment variable `LICENSE` equal to `accept` when running the image. You can also view the license terms by setting this variable to `view`. Failure to set the variable will result in the termination of the container with a usage statement. You can view the license in a different language by also setting the `LANG` environment variable.
|
||||
|
||||
> **Note**: You can use `podman` instead of `docker` in any of the examples on this page.
|
||||
|
||||
## Running with the default configuration
|
||||
You can run a queue manager with the default configuration and a listener on port 1414 using the following command. For example, the following command creates and starts a queue manager called `QM1`, and maps port 1414 on the host to the MQ listener on port 1414 inside the container, as well as port 9443 on the host to the web console on port 9443 inside the container:
|
||||
|
||||
@@ -58,23 +60,18 @@ You can customize the configuration in several ways:
|
||||
|
||||
1. For getting started, you can use the [default developer configuration](developer-config.md), which is available out-of-the-box for the MQ Advanced for Developers image
|
||||
2. By creating your own image and adding your own MQSC file into the `/etc/mqm` directory on the image. This file will be run when your queue manager is created.
|
||||
3. By using [remote MQ administration](https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.1.0/com.ibm.mq.adm.doc/q021090_.htm), via an MQ command server, the MQ HTTP APIs, or using a tool such as the MQ web console or MQ Explorer.
|
||||
3. By using [remote MQ administration](https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.2.0/com.ibm.mq.adm.doc/q021090_.htm), via an MQ command server, the MQ HTTP APIs, or using a tool such as the MQ web console or MQ Explorer.
|
||||
|
||||
Note that a listener is always created on port 1414 inside the container. This port can be mapped to any port on the Docker host.
|
||||
|
||||
The following is an *example* `Dockerfile` for creating your own pre-configured image, which adds a custom MQ configuration file, and an administrative user `alice`. Note that it is not normally recommended to include passwords in this way:
|
||||
The following is an *example* `Dockerfile` for creating your own pre-configured image, which adds a custom MQ configuration file:
|
||||
|
||||
```dockerfile
|
||||
FROM ibmcom/mq
|
||||
USER root
|
||||
RUN useradd alice -G mqm && \
|
||||
echo alice:passw0rd | chpasswd
|
||||
USER mqm
|
||||
USER 1001
|
||||
COPY 20-config.mqsc /etc/mqm/
|
||||
```
|
||||
|
||||
The `USER` instructions are necessary to ensure that the `useradd` and `chpasswd` commands are run as the root user.
|
||||
|
||||
Here is an example corresponding `20-config.mqsc` script, which creates two local queues:
|
||||
|
||||
```mqsc
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
* Set the keystore location for the queue manager
|
||||
ALTER QMGR SSLKEYR('{{ .SSLKeyR }}')
|
||||
ALTER QMGR CERTLABL('{{ .CertificateLabel }}')
|
||||
|
||||
REFRESH SECURITY(*) TYPE(SSL)
|
||||
|
||||
2
etc/mqm/mq.htpasswd
Normal file
2
etc/mqm/mq.htpasswd
Normal file
@@ -0,0 +1,2 @@
|
||||
admin:$2y$05$M/C1U62RZ6q1kv4E7.S7ueNESJmFe85RsZcoMUReRXUDB8QcP3yqS
|
||||
app:$2y$05$BnbPtcjXTjk5JRJ8gzHqIuHgoQbLF3qtbPV3Q3tLyr0XJNg.7dkxW
|
||||
11
etc/mqm/qm-service-component.ini
Normal file
11
etc/mqm/qm-service-component.ini
Normal file
@@ -0,0 +1,11 @@
|
||||
ServiceComponent:
|
||||
Service=AuthorizationService
|
||||
Name=Dev.HtpAuth.Service
|
||||
Module=/opt/mqm/lib64/amqpasdev.so
|
||||
ComponentDataSize=0
|
||||
ServiceComponent:
|
||||
Service=AuthorizationService
|
||||
Name=MQSeries.UNIX.auth.service
|
||||
Module=amqzfu
|
||||
ComponentDataSize=0
|
||||
|
||||
57
glide.lock
generated
57
glide.lock
generated
@@ -1,57 +0,0 @@
|
||||
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: []
|
||||
30
glide.yaml
30
glide.yaml
@@ -1,30 +0,0 @@
|
||||
# © Copyright IBM Corporation 2017, 2019
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# 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: github.com/ibm-messaging/mq-container
|
||||
license: Apache-2.0
|
||||
excludeDirs:
|
||||
- build
|
||||
- coverage
|
||||
- test
|
||||
import:
|
||||
- package: golang.org/x/sys/unix
|
||||
- package: github.com/prometheus/client_golang
|
||||
version: 0.8.0
|
||||
- package: github.com/ibm-messaging/mq-golang
|
||||
version: 2.0.0
|
||||
- package: github.com/genuinetools/amicontained
|
||||
version: 0.4.0
|
||||
- package: software.sslmate.com/src/go-pkcs12
|
||||
commit: 6e380ad96778cc63c6ea17649a9b74224bceafe9
|
||||
@@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM registry.access.redhat.com/ubi7/ubi-minimal AS mq-explorer
|
||||
FROM registry.redhat.io/ubi8/ubi-minimal AS mq-explorer
|
||||
|
||||
# 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"
|
||||
@@ -22,7 +22,7 @@ ENV MQ_PACKAGES="MQSeriesRuntime*.rpm MQSeriesJRE*.rpm MQSeriesExplorer*.rpm"
|
||||
|
||||
ARG MQM_UID=888
|
||||
|
||||
RUN microdnf install -y --nodocs gtk2 libXtst \
|
||||
RUN microdnf install -y gtk2 libXtst \
|
||||
&& microdnf clean all
|
||||
|
||||
ADD install-mq.sh /usr/local/bin/
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM registry.access.redhat.com/rhscl/devtoolset-7-toolchain-rhel7 AS mq-sdk
|
||||
FROM registry.redhat.io/rhel8/llvm-toolset:8.0.1-10 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
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
STOP LISTENER('SYSTEM.LISTENER.TCP.1') IGNSTATE(YES)
|
||||
ALTER LISTENER('SYSTEM.LISTENER.TCP.1') TRPTYPE(TCP) CONTROL(MANUAL)
|
||||
|
||||
* Developer queues
|
||||
DEFINE QLOCAL('DEV.QUEUE.1') REPLACE
|
||||
DEFINE QLOCAL('DEV.QUEUE.2') REPLACE
|
||||
@@ -43,12 +40,9 @@ SET CHLAUTH('*') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(NOACCESS) DESCR('Back-sto
|
||||
SET CHLAUTH('DEV.APP.SVRCONN') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT({{ .ChckClnt }}) DESCR('Allows connection via APP channel') ACTION(REPLACE)
|
||||
SET CHLAUTH('DEV.ADMIN.SVRCONN') TYPE(BLOCKUSER) USERLIST('nobody') DESCR('Allows admins on ADMIN channel') ACTION(REPLACE)
|
||||
SET CHLAUTH('DEV.ADMIN.SVRCONN') TYPE(USERMAP) CLNTUSER('admin') USERSRC(CHANNEL) DESCR('Allows admin user to connect via ADMIN channel') ACTION(REPLACE)
|
||||
SET CHLAUTH('DEV.ADMIN.SVRCONN') TYPE(USERMAP) CLNTUSER('admin') USERSRC(MAP) MCAUSER ('mqm') DESCR ('Allow admin as MQ-admin') ACTION(REPLACE)
|
||||
|
||||
* Developer authority records
|
||||
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(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)
|
||||
SET AUTHREC PRINCIPAL('app') OBJTYPE(QMGR) AUTHADD(CONNECT,INQ)
|
||||
SET AUTHREC PROFILE('DEV.**') PRINCIPAL('app') OBJTYPE(QUEUE) AUTHADD(BROWSE,GET,INQ,PUT)
|
||||
SET AUTHREC PROFILE('DEV.**') PRINCIPAL('app') OBJTYPE(TOPIC) AUTHADD(PUB,SUB)
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
* limitations under the License.
|
||||
|
||||
* Set the cipherspec for dev channels
|
||||
ALTER CHANNEL('DEV.APP.SVRCONN') CHLTYPE(SVRCONN) SSLCIPH({{ .SSLCipherSpec }}) SSLCAUTH(OPTIONAL)
|
||||
ALTER CHANNEL('DEV.ADMIN.SVRCONN') CHLTYPE(SVRCONN) SSLCIPH({{ .SSLCipherSpec }}) SSLCAUTH(OPTIONAL)
|
||||
ALTER CHANNEL('DEV.APP.SVRCONN') CHLTYPE(SVRCONN) SSLCIPH(ANY_TLS12) SSLCAUTH(OPTIONAL)
|
||||
ALTER CHANNEL('DEV.ADMIN.SVRCONN') CHLTYPE(SVRCONN) SSLCIPH(ANY_TLS12) SSLCAUTH(OPTIONAL)
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# 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/microdnf && MICRODNF=true || MICRODNF=false
|
||||
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
|
||||
@@ -33,6 +36,6 @@ if ($YUM); then
|
||||
fi
|
||||
|
||||
if ($MICRODNF); then
|
||||
microdnf install --nodocs sudo
|
||||
microdnf install sudo
|
||||
microdnf clean all
|
||||
fi
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
set -ex
|
||||
|
||||
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 curl -Lo /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.5.1/dep-linux-$ARCH
|
||||
sudo chmod +x /usr/local/bin/dep
|
||||
|
||||
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."
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © Copyright IBM Corporation 2015, 2019
|
||||
# © Copyright IBM Corporation 2015, 2020
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -63,10 +63,10 @@ if ($UBUNTU); then
|
||||
fi
|
||||
|
||||
if ($RPM); then
|
||||
EXTRA_RPMS="bash bc ca-certificates coreutils file findutils gawk glibc-common grep passwd procps-ng sed shadow-utils tar util-linux which"
|
||||
EXTRA_RPMS="bash bc ca-certificates file findutils gawk glibc-common grep ncurses-compat-libs passwd procps-ng sed shadow-utils tar util-linux which"
|
||||
# Install additional packages required by MQ, this install process and the runtime scripts
|
||||
$YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS}
|
||||
$MICRODNF && microdnf install --nodocs ${EXTRA_RPMS}
|
||||
$MICRODNF && microdnf install ${EXTRA_RPMS}
|
||||
fi
|
||||
|
||||
# Apply any bug fixes not included in base Ubuntu or MQ image.
|
||||
|
||||
105
install-mq.sh
105
install-mq.sh
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © Copyright IBM Corporation 2015, 2019
|
||||
# © Copyright IBM Corporation 2015, 2020
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,74 +18,70 @@
|
||||
# Fail on any non-zero return code
|
||||
set -ex
|
||||
|
||||
mqm_uid=${1:-888}
|
||||
|
||||
test -f /usr/bin/yum && YUM=true || YUM=false
|
||||
test -f /usr/bin/microdnf && MICRODNF=true || MICRODNF=false
|
||||
test -f /usr/bin/rpm && RPM=true || RPM=false
|
||||
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
|
||||
|
||||
# Download and extract the MQ installation files
|
||||
DIR_EXTRACT=/tmp/mq
|
||||
mkdir -p ${DIR_EXTRACT}
|
||||
cd ${DIR_EXTRACT}
|
||||
# Only install the SDK package as part of the build stage
|
||||
INSTALL_SDK=${INSTALL_SDK:-0}
|
||||
|
||||
# Download and extract the MQ unzippable server
|
||||
DIR_TMP=/tmp/mq
|
||||
mkdir -p ${DIR_TMP}
|
||||
cd ${DIR_TMP}
|
||||
curl -LO $MQ_URL
|
||||
tar -zxf ./*.tar.gz
|
||||
|
||||
# Recommended: Create the mqm user ID with a fixed UID and group, so that the file permissions work between different images
|
||||
groupadd --system --gid ${mqm_uid} mqm
|
||||
useradd --system --uid ${mqm_uid} --gid mqm --groups 0 mqm
|
||||
tar -xzf ./*.tar.gz
|
||||
rm -f ./*.tar.gz
|
||||
ls -la ${DIR_TMP}
|
||||
|
||||
# Find directory containing .deb files
|
||||
$UBUNTU && DIR_DEB=$(find ${DIR_EXTRACT} -name "*.deb" -printf "%h\n" | sort -u | head -1)
|
||||
$RPM && DIR_RPM=$(find ${DIR_EXTRACT} -name "*.rpm" -printf "%h\n" | sort -u | head -1)
|
||||
# Find location of mqlicense.sh
|
||||
MQLICENSE=$(find ${DIR_EXTRACT} -name "mqlicense.sh")
|
||||
# Generate MQ package in INSTALLATION_DIR
|
||||
export genmqpkg_inc32=0
|
||||
export genmqpkg_incadm=1
|
||||
export genmqpkg_incamqp=0
|
||||
export genmqpkg_incams=1
|
||||
export genmqpkg_inccbl=0
|
||||
export genmqpkg_inccics=0
|
||||
export genmqpkg_inccpp=0
|
||||
export genmqpkg_incdnet=0
|
||||
export genmqpkg_incjava=1
|
||||
export genmqpkg_incjre=1
|
||||
export genmqpkg_incman=0
|
||||
export genmqpkg_incmqbc=0
|
||||
export genmqpkg_incmqft=0
|
||||
export genmqpkg_incmqsf=0
|
||||
export genmqpkg_incmqxr=0
|
||||
export genmqpkg_incnls=1
|
||||
export genmqpkg_incras=1
|
||||
export genmqpkg_incsamp=1
|
||||
export genmqpkg_incsdk=$INSTALL_SDK
|
||||
export genmqpkg_inctls=1
|
||||
export genmqpkg_incunthrd=0
|
||||
export genmqpkg_incweb=1
|
||||
export INSTALLATION_DIR=/opt/mqm
|
||||
${DIR_TMP}/bin/genmqpkg.sh -b ${INSTALLATION_DIR}
|
||||
ls -la ${INSTALLATION_DIR}
|
||||
rm -rf ${DIR_TMP}
|
||||
|
||||
# Accept the MQ license
|
||||
${MQLICENSE} -text_only -accept
|
||||
$UBUNTU && echo "deb [trusted=yes] file:${DIR_DEB} ./" > /etc/apt/sources.list.d/IBM_MQ.list
|
||||
|
||||
# Install MQ using the DEB packages
|
||||
$UBUNTU && apt-get update
|
||||
$UBUNTU && apt-get install -y $MQ_PACKAGES
|
||||
|
||||
$RPM && cd $DIR_RPM && rpm -ivh $MQ_PACKAGES
|
||||
|
||||
# Remove 32-bit libraries from 64-bit container
|
||||
# The "file" utility isn't installed by default in UBI, so only try this if it's installed
|
||||
which file && find /opt/mqm /var/mqm -type f -exec file {} \; | awk -F: '/ELF 32-bit/{print $1}' | xargs --no-run-if-empty rm -f
|
||||
|
||||
# Remove tar.gz files unpacked by RPM postinst scripts
|
||||
find /opt/mqm -name '*.tar.gz' -delete
|
||||
|
||||
# Recommended: Set the default MQ installation (makes the MQ commands available on the PATH)
|
||||
/opt/mqm/bin/setmqinst -p /opt/mqm -i
|
||||
|
||||
# Clean up all the downloaded files
|
||||
$UBUNTU && rm -f /etc/apt/sources.list.d/IBM_MQ.list
|
||||
rm -rf ${DIR_EXTRACT}
|
||||
${INSTALLATION_DIR}/bin/mqlicense -accept
|
||||
|
||||
# Optional: Update the command prompt with the MQ version
|
||||
$UBUNTU && echo "mq:$(dspmqver -b -f 2)" > /etc/debian_chroot
|
||||
|
||||
# Remove the directory structure under /var/mqm which was created by the installer
|
||||
rm -rf /var/mqm
|
||||
|
||||
# Create the mount point for volumes, ensuring MQ has permissions to all directories
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm/data
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-log
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-log/log
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-data
|
||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-data/qmgrs
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm/data
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-log
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-log/log
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-data
|
||||
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-data/qmgrs
|
||||
|
||||
# Create the directory for MQ configuration files
|
||||
install --directory --mode 0775 --owner mqm --group root /etc/mqm
|
||||
install --directory --mode 2775 --owner 1001 --group root /etc/mqm
|
||||
|
||||
# Create the directory for MQ runtime files
|
||||
install --directory --mode 0775 --owner mqm --group root /run/mqm
|
||||
install --directory --mode 2775 --owner 1001 --group root /run/mqm
|
||||
|
||||
# Create a symlink for /var/mqm -> /mnt/mqm/data
|
||||
ln -s /mnt/mqm/data /var/mqm
|
||||
@@ -94,7 +90,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_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/# minlen = 9/minlen = 8/' /etc/security/pwquality.conf
|
||||
$RPM && sed -i 's/# minlen/minlen/' /etc/security/pwquality.conf
|
||||
|
||||
$UBUNTU && PAM_FILE=/etc/pam.d/common-password
|
||||
$RPM && PAM_FILE=/etc/pam.d/password-auth
|
||||
@@ -104,6 +100,9 @@ sed -i 's/password\t\[success=1 default=ignore\]\tpam_unix\.so obscure sha512/pa
|
||||
$RPM && rpm -q --all || 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
|
||||
mkdir -p /licenses
|
||||
cp /opt/mqm/licenses/*.txt /licenses/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2018
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -20,69 +20,20 @@ package command
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"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
|
||||
// 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 Run(name string, arg ...string) (string, int, error) {
|
||||
// #nosec G204
|
||||
return RunCmd(exec.Command(name, arg...))
|
||||
}
|
||||
|
||||
// RunAsMQM runs the specified command as the mqm user
|
||||
func RunAsMQM(name string, arg ...string) (string, int, error) {
|
||||
// Run the command and wait for completion
|
||||
// #nosec G204
|
||||
cmd := exec.Command(name, arg...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
uid, gid, err := LookupMQM()
|
||||
out, err := cmd.CombinedOutput()
|
||||
rc := cmd.ProcessState.ExitCode()
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
return string(out), rc, fmt.Errorf("%v: %v", cmd.Path, err)
|
||||
}
|
||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||
return RunCmd(cmd)
|
||||
}
|
||||
|
||||
// LookupMQM looks up the UID & GID of the mqm user
|
||||
func LookupMQM() (int, int, error) {
|
||||
mqm, err := user.Lookup("mqm")
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
mqmUID, err := strconv.Atoi(mqm.Uid)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
mqmGID, err := strconv.Atoi(mqm.Gid)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
return mqmUID, mqmGID, nil
|
||||
return string(out), rc, nil
|
||||
}
|
||||
|
||||
153
internal/htpasswd/htpasswd.go
Normal file
153
internal/htpasswd/htpasswd.go
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2020
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
//This is a developer only configuration and not recommended for production usage.
|
||||
|
||||
package htpasswd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type mapHtPasswd map[string]string
|
||||
|
||||
func encryptPassword(password string) (string, error) {
|
||||
passwordBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(passwordBytes), nil
|
||||
}
|
||||
|
||||
// SetPassword sets encrypted password for the user into htpasswd file
|
||||
func SetPassword(user string, password string, isTest bool) error {
|
||||
|
||||
if len(strings.TrimSpace(user)) == 0 || len(strings.TrimSpace(password)) == 0 {
|
||||
return fmt.Errorf("UserId or Password are empty")
|
||||
}
|
||||
|
||||
passwords := mapHtPasswd(map[string]string{})
|
||||
|
||||
// Read the password file
|
||||
err := passwords.ReadHtPasswordFile(isTest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pwd, err := encryptPassword(password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set the new password
|
||||
passwords[user] = pwd
|
||||
|
||||
// Update the password file
|
||||
return passwords.updateHtPasswordFile(isTest)
|
||||
}
|
||||
|
||||
// GetBytes return the Bytes representation of the htpassword file
|
||||
func (htpfile mapHtPasswd) GetBytes() (passwordBytes []byte) {
|
||||
passwordBytes = []byte{}
|
||||
for name, hash := range htpfile {
|
||||
passwordBytes = append(passwordBytes, []byte(name+":"+hash+"\n")...)
|
||||
}
|
||||
return passwordBytes
|
||||
}
|
||||
|
||||
// ReadHtPasswordFile parses the htpasswd file
|
||||
func (htpfile mapHtPasswd) ReadHtPasswordFile(isTest bool) error {
|
||||
|
||||
file := "/etc/mqm/mq.htpasswd"
|
||||
if isTest {
|
||||
file = "my.htpasswd"
|
||||
}
|
||||
|
||||
pwdsBytes, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(pwdsBytes), "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
for i, part := range parts {
|
||||
parts[i] = strings.TrimSpace(part)
|
||||
}
|
||||
htpfile[parts[0]] = parts[1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (htpfile mapHtPasswd) updateHtPasswordFile(isTest bool) error {
|
||||
|
||||
file := "/etc/mqm/mq.htpasswd"
|
||||
if isTest {
|
||||
file = "my.htpasswd"
|
||||
}
|
||||
return ioutil.WriteFile(file, htpfile.GetBytes(), 0660)
|
||||
}
|
||||
|
||||
// AuthenticateUser verifies if the given user password match with htpasswrd
|
||||
func AuthenticateUser(user string, password string, isTest bool) (bool, bool, error) {
|
||||
passwords := mapHtPasswd(map[string]string{})
|
||||
|
||||
if len(strings.TrimSpace(user)) == 0 || len(strings.TrimSpace(password)) == 0 {
|
||||
return false, false, fmt.Errorf("UserId or Password are empty")
|
||||
}
|
||||
|
||||
err := passwords.ReadHtPasswordFile(isTest)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
ok := false
|
||||
value, found := passwords[user]
|
||||
|
||||
if !found {
|
||||
return found, ok, fmt.Errorf("User not found in the mq.htpasswd file")
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(value), []byte(password))
|
||||
return found, err == nil, err
|
||||
}
|
||||
|
||||
// ValidateUser validates the given user
|
||||
func ValidateUser(user string, isTest bool) (bool, error) {
|
||||
passwords := mapHtPasswd(map[string]string{})
|
||||
|
||||
if len(strings.TrimSpace(user)) == 0 {
|
||||
return false, fmt.Errorf("Userid is empty for AuthenticateUser")
|
||||
}
|
||||
|
||||
err := passwords.ReadHtPasswordFile(isTest)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
_, found := passwords[strings.TrimSpace(user)]
|
||||
return found, nil
|
||||
}
|
||||
62
internal/htpasswd/htpasswd_test.go
Normal file
62
internal/htpasswd/htpasswd_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2020
|
||||
|
||||
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 htpasswd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCheckUser verifies Htpassword's use
|
||||
func TestCheckUser(t *testing.T) {
|
||||
err := SetPassword("guest", "guestpw", true)
|
||||
if err != nil {
|
||||
t.Fatalf("htpassword test failed due to error:%s\n", err.Error())
|
||||
}
|
||||
found, ok, err := AuthenticateUser("guest", "guestpw", true)
|
||||
if err != nil {
|
||||
t.Fatalf("htpassword test1 failed as user could not be found:%s\n", err.Error())
|
||||
}
|
||||
if found == false || ok == false {
|
||||
t.Fatalf("htpassword test1 failed as user could not be found:%v, ok:%v\n", found, ok)
|
||||
}
|
||||
|
||||
found, ok, err = AuthenticateUser("myguest", "guestpw", true)
|
||||
if err == nil {
|
||||
t.Fatalf("htpassword test2 failed as no error received for non-existing user\n")
|
||||
}
|
||||
if found == true || ok == true {
|
||||
t.Fatalf("htpassword test2 failed for non-existing user found :%v, ok:%v\n", found, ok)
|
||||
}
|
||||
|
||||
found, ok, err = AuthenticateUser("guest", "guest", true)
|
||||
if err == nil {
|
||||
t.Fatalf("htpassword test3 failed as incorrect password of user did not return error\n")
|
||||
}
|
||||
|
||||
if found == false || ok == true {
|
||||
t.Fatalf("htpassword test3 failed for existing user with incorrect passwored found :%v, ok:%v\n", found, ok)
|
||||
}
|
||||
|
||||
found, err = ValidateUser("guest", true)
|
||||
if err != nil || found == false {
|
||||
t.Fatalf("htpassword test4 failed as user could not be found:%v, ok:%v\n", found, ok)
|
||||
}
|
||||
|
||||
found, err = ValidateUser("myguest", true)
|
||||
if err != nil || found == true {
|
||||
t.Fatalf("htpassword test5 failed as non-existing user returned to be found:%v, ok:%v\n", found, ok)
|
||||
}
|
||||
}
|
||||
1
internal/htpasswd/my.htpasswd
Normal file
1
internal/htpasswd/my.htpasswd
Normal file
@@ -0,0 +1 @@
|
||||
guest:$2y$05$ifFP0nCmFed6.m4iB9CHRuHFps2YeeuwopmOvszWt0GRnN59p8qxW
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
© Copyright IBM Corporation 2018, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -105,14 +105,6 @@ func (ks *KeyStore) Create() error {
|
||||
return fmt.Errorf("error running \"%v -keydb -create\": %v %s", ks.command, err, out)
|
||||
}
|
||||
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chown(ks.Filename, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -130,14 +122,6 @@ func (ks *KeyStore) CreateStash() error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chown(stashFile, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -152,7 +136,7 @@ func (ks *KeyStore) Import(inputFile, password string) error {
|
||||
|
||||
// CreateSelfSignedCertificate creates a self-signed certificate in the keystore
|
||||
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)
|
||||
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")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running \"%v -cert -create\": %v %s", ks.command, err, out)
|
||||
}
|
||||
@@ -207,7 +191,7 @@ func (ks *KeyStore) RenameCertificate(from, to string) error {
|
||||
// #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.Env = append(os.Environ(), "LD_LIBRARY_PATH=/opt/mqm/gskit8/lib64/:/opt/mqm/gskit8/lib")
|
||||
out, _, err := command.RunCmd(cmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running \"%v -cert -rename\": %v %s", "/opt/mqm/gskit8/bin/gsk8capicmd_64", err, out)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/ibm-messaging/mq-golang/ibmmq"
|
||||
"github.com/ibm-messaging/mq-golang/mqmetric"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
"github.com/ibm-messaging/mq-golang/mqmetric"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
© Copyright IBM Corporation 2018, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -22,8 +22,7 @@ import (
|
||||
"path"
|
||||
"text/template"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
)
|
||||
|
||||
// ProcessTemplateFile takes a Go templateFile, and processes it with the
|
||||
@@ -45,16 +44,6 @@ func ProcessTemplateFile(templateFile, destFile string, data interface{}, log *l
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
err = os.Chown(dir, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -67,15 +56,5 @@ func ProcessTemplateFile(templateFile, destFile string, data interface{}, log *l
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
mqmUID, mqmGID, err := command.LookupMQM()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
err = os.Chown(destFile, mqmUID, mqmGID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
299
internal/qmgrauth/pas.go
Normal file
299
internal/qmgrauth/pas.go
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2020
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
//This is a developer only configuration and not recommended for production usage.
|
||||
package main
|
||||
|
||||
/*
|
||||
#cgo !windows CFLAGS: -I/opt/mqm/lib64 -D_REENTRANT
|
||||
#cgo !windows,!darwin LDFLAGS: -L/opt/mqm/lib64 -lmqm_r -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64
|
||||
#cgo darwin LDFLAGS: -L/opt/mqm/lib64 -lmqm_r -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64
|
||||
#cgo windows CFLAGS: -I"C:/Program Files/IBM/MQ/Tools/c/include"
|
||||
#cgo windows LDFLAGS: -L "C:/Program Files/IBM/MQ/bin64" -lmqm
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cmqc.h>
|
||||
#include <cmqxc.h>
|
||||
#include <cmqzc.h>
|
||||
#include <cmqec.h>
|
||||
#include <time.h>
|
||||
static MQZ_INIT_AUTHORITY PASStart;
|
||||
static MQZ_AUTHENTICATE_USER OAAuthUser;
|
||||
static MQZ_FREE_USER OAFreeUser;
|
||||
static MQZ_TERM_AUTHORITY OATermAuth;
|
||||
extern int Authenticate(char *, char *);
|
||||
extern int CheckAuthority(char *);
|
||||
static char *OAEnvStr(MQLONG);
|
||||
static void FindSize();
|
||||
static void PrintDateTime();
|
||||
static FILE *fp = NULL;
|
||||
static int primary_process = 0;
|
||||
|
||||
static void MQENTRY PASStart(
|
||||
MQHCONFIG hc,
|
||||
MQLONG Options,
|
||||
MQCHAR48 QMgrName,
|
||||
MQLONG ComponentDataLength,
|
||||
PMQBYTE ComponentData,
|
||||
PMQLONG Version,
|
||||
PMQLONG pCompCode,
|
||||
PMQLONG pReason) {
|
||||
MQLONG CC = MQCC_OK;
|
||||
MQLONG Reason = MQRC_NONE;
|
||||
|
||||
if ((Options & MQZIO_PRIMARY) == MQZIO_PRIMARY)
|
||||
primary_process = 1;
|
||||
|
||||
fp=fopen("/var/mqm/errors/amqpasdev.log","a");
|
||||
|
||||
if (CC == MQCC_OK)
|
||||
hc->MQZEP_Call(hc, MQZID_INIT_AUTHORITY,(PMQFUNC)PASStart,&CC,&Reason);
|
||||
|
||||
if (CC == MQCC_OK)
|
||||
hc->MQZEP_Call(hc,MQZID_TERM_AUTHORITY,(PMQFUNC)OATermAuth,&CC,&Reason);
|
||||
|
||||
if (CC == MQCC_OK)
|
||||
hc->MQZEP_Call(hc,MQZID_AUTHENTICATE_USER,(PMQFUNC)OAAuthUser,&CC,&Reason);
|
||||
|
||||
if (CC == MQCC_OK)
|
||||
hc->MQZEP_Call(hc,MQZID_FREE_USER,(PMQFUNC)OAFreeUser,&CC,&Reason);
|
||||
|
||||
*Version = MQZAS_VERSION_5;
|
||||
*pCompCode = CC;
|
||||
*pReason = Reason;
|
||||
|
||||
PrintDateTime();
|
||||
fprintf(fp, "Pluggable OAM Initialized.\n");
|
||||
fprintf(fp, "THIS IS A DEVELOPER ONLY CONFIGURATION AND NOT RECOMMENDED FOR PRODUCTION USAGE");
|
||||
return;
|
||||
}
|
||||
|
||||
static char *authuserfmt =
|
||||
"\tUser : \"%12.12s\"\n"\
|
||||
"\tEffUser : \"%12.12s\"\n"\
|
||||
"\tAppName : \"%28.28s\"\n"\
|
||||
"\tApIdDt : \"%32.32s\"\n"\
|
||||
"\tEnv : \"%s\"\n"\
|
||||
"\tApp Pid : %d\n"\
|
||||
"\tApp Tid : %d\n"\
|
||||
;
|
||||
static void MQENTRY OAAuthUser (
|
||||
PMQCHAR pQMgrName,
|
||||
PMQCSP pSecurityParms,
|
||||
PMQZAC pApplicationContext,
|
||||
PMQZIC pIdentityContext,
|
||||
PMQPTR pCorrelationPtr,
|
||||
PMQBYTE pComponentData,
|
||||
PMQLONG pContinuation,
|
||||
PMQLONG pCompCode,
|
||||
PMQLONG pReason)
|
||||
{
|
||||
char *spuser = NULL;
|
||||
char *sppass = NULL;
|
||||
int gorc = MQRC_NOT_AUTHORIZED;
|
||||
|
||||
if ((pSecurityParms->CSPUserIdLength) > 0) {
|
||||
//Grab the user creds from csp.
|
||||
spuser = malloc(pSecurityParms->CSPUserIdLength+1);
|
||||
strncpy(spuser,pSecurityParms->CSPUserIdPtr,pSecurityParms->CSPUserIdLength);
|
||||
spuser[pSecurityParms->CSPUserIdLength]=0;
|
||||
sppass = malloc(pSecurityParms->CSPPasswordLength+1);
|
||||
strncpy(sppass,pSecurityParms->CSPPasswordPtr,pSecurityParms->CSPPasswordLength);
|
||||
sppass[pSecurityParms->CSPPasswordLength]=0;
|
||||
gorc = Authenticate(spuser,sppass);
|
||||
|
||||
if (gorc == MQRC_NONE) {
|
||||
*pCompCode = MQCC_OK;
|
||||
*pReason = MQRC_NONE;
|
||||
*pContinuation = MQZCI_CONTINUE;
|
||||
memcpy( pIdentityContext->UserIdentifier
|
||||
, spuser
|
||||
, sizeof(pIdentityContext->UserIdentifier) );
|
||||
} else {
|
||||
*pCompCode = MQCC_WARNING;
|
||||
*pReason = MQRC_NONE;
|
||||
*pContinuation = MQZCI_CONTINUE;
|
||||
//we print to error file only if error'd
|
||||
PrintDateTime();
|
||||
if (fp) {
|
||||
fprintf(fp, authuserfmt,
|
||||
pIdentityContext->UserIdentifier,
|
||||
pApplicationContext->EffectiveUserID,
|
||||
pApplicationContext->ApplName,
|
||||
pIdentityContext->ApplIdentityData,
|
||||
OAEnvStr(pApplicationContext->Environment),
|
||||
pApplicationContext->ProcessId,
|
||||
pApplicationContext->ThreadId);
|
||||
|
||||
fprintf(fp,"\tCSP UserId : %s\n", spuser);
|
||||
fprintf(fp,"\tCSP Password : %s\n", "****..");
|
||||
fprintf(fp,"\tPAS-Compcode:%d\n",*pCompCode);
|
||||
fprintf(fp,"\tPAS-Reasoncode:%d\n",*pReason);
|
||||
}
|
||||
}
|
||||
free(spuser);
|
||||
free(sppass);
|
||||
} else {
|
||||
//this is only a normal UID authentication.
|
||||
spuser = malloc(sizeof(PMQCHAR12));
|
||||
strncpy(spuser,pApplicationContext->EffectiveUserID,strlen(pApplicationContext->EffectiveUserID));
|
||||
spuser[sizeof(PMQCHAR12)]=0;
|
||||
gorc = CheckAuthority(spuser);
|
||||
if (gorc == MQRC_NONE){
|
||||
*pCompCode = MQCC_OK;
|
||||
*pReason = MQRC_NONE;
|
||||
*pContinuation = MQZCI_CONTINUE;
|
||||
memcpy( pIdentityContext->UserIdentifier
|
||||
, spuser
|
||||
, sizeof(pIdentityContext->UserIdentifier) );
|
||||
} else {
|
||||
*pCompCode = MQCC_WARNING;
|
||||
*pReason = MQRC_NONE;
|
||||
*pContinuation = MQZCI_CONTINUE;
|
||||
//we print only if error'd
|
||||
PrintDateTime();
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, authuserfmt,
|
||||
pIdentityContext->UserIdentifier,
|
||||
pApplicationContext->EffectiveUserID,
|
||||
pApplicationContext->ApplName,
|
||||
pIdentityContext->ApplIdentityData,
|
||||
OAEnvStr(pApplicationContext->Environment),
|
||||
pApplicationContext->ProcessId,
|
||||
pApplicationContext->ThreadId
|
||||
);
|
||||
fprintf(fp,"\tUID : %s\n", spuser);
|
||||
fprintf(fp,"\tPAS-Compcode:%d\n",*pCompCode);
|
||||
fprintf(fp,"\tPAS-Reasoncode:%d\n",*pReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void MQENTRY OAFreeUser (
|
||||
PMQCHAR pQMgrName,
|
||||
PMQZFP pFreeParms,
|
||||
PMQBYTE pComponentData,
|
||||
PMQLONG pContinuation,
|
||||
|
||||
PMQLONG pCompCode,
|
||||
PMQLONG pReason)
|
||||
{
|
||||
*pCompCode = MQCC_WARNING;
|
||||
*pReason = MQRC_NONE;
|
||||
*pContinuation = MQZCI_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
static void MQENTRY OATermAuth(
|
||||
MQHCONFIG hc,
|
||||
MQLONG Options,
|
||||
PMQCHAR pQMgrName,
|
||||
PMQBYTE pComponentData,
|
||||
PMQLONG pCompCode,
|
||||
PMQLONG pReason)
|
||||
{
|
||||
if ((primary_process) && ((Options & MQZTO_PRIMARY) == MQZTO_PRIMARY) ||
|
||||
((Options & MQZTO_SECONDARY) == MQZTO_SECONDARY))
|
||||
{
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
}
|
||||
*pCompCode = MQCC_OK;
|
||||
*pReason = MQRC_NONE;
|
||||
}
|
||||
|
||||
static void PrintDateTime() {
|
||||
FindSize();
|
||||
struct tm *local;
|
||||
time_t t;
|
||||
t = time(NULL);
|
||||
local = localtime(&t);
|
||||
if (fp) {
|
||||
fprintf(fp, "-------------------------------------------------\n");
|
||||
fprintf(fp, "Local time: %s", asctime(local));
|
||||
local = gmtime(&t);
|
||||
fprintf(fp, "UTC time: %s", asctime(local));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static char *OAEnvStr(MQLONG x)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case MQXE_OTHER: return "Application";
|
||||
case MQXE_MCA: return "Channel";
|
||||
case MQXE_MCA_SVRCONN: return "Channel SvrConn";
|
||||
case MQXE_COMMAND_SERVER: return "Command Server";
|
||||
case MQXE_MQSC: return "MQSC";
|
||||
default: return "Invalid Environment";
|
||||
}
|
||||
}
|
||||
|
||||
static void FindSize()
|
||||
{
|
||||
int sz = 0;
|
||||
int prev=ftell(fp);
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
sz=ftell(fp);
|
||||
//if log file size goes over 1mb, rewind it.
|
||||
if (sz > 1000000) {
|
||||
rewind(fp);
|
||||
} else {
|
||||
fseek(fp, prev, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import "github.com/ibm-messaging/mq-container/internal/htpasswd"
|
||||
|
||||
//export MQStart
|
||||
func MQStart(hc C.MQHCONFIG, Options C.MQLONG, QMgrName C.PMQCHAR, ComponentDataLength C.MQLONG, ComponentData C.PMQBYTE, Version C.PMQLONG, pCompCode C.PMQLONG, pReason C.PMQLONG) {
|
||||
C.PASStart(hc, Options, QMgrName, ComponentDataLength, ComponentData, Version, pCompCode, pReason)
|
||||
}
|
||||
|
||||
//export Authenticate
|
||||
func Authenticate(x *C.char, y *C.char) C.int {
|
||||
user := C.GoString(x)
|
||||
pwd := C.GoString(y)
|
||||
found, ok, err := htpasswd.AuthenticateUser(user, pwd, false)
|
||||
|
||||
if !found || !ok || err != nil {
|
||||
return C.MQRC_UNKNOWN_OBJECT_NAME
|
||||
}
|
||||
return C.MQRC_NONE
|
||||
}
|
||||
|
||||
//export CheckAuthority
|
||||
func CheckAuthority(x *C.char) C.int {
|
||||
user := C.GoString(x)
|
||||
found, err := htpasswd.ValidateUser(user, false)
|
||||
if !found || err != nil {
|
||||
return C.MQRC_UNKNOWN_OBJECT_NAME
|
||||
}
|
||||
return C.MQRC_NONE
|
||||
|
||||
}
|
||||
|
||||
func main() {}
|
||||
File diff suppressed because it is too large
Load Diff
97
internal/tls/tls_web.go
Normal file
97
internal/tls/tls_web.go
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2019, 2020
|
||||
|
||||
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 tls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/keystore"
|
||||
)
|
||||
|
||||
// webKeystoreDefault is the name of the default web server Keystore
|
||||
const webKeystoreDefault = "default.p12"
|
||||
|
||||
// ConfigureWebTLS configures TLS for the web server
|
||||
func ConfigureWebTLS(keyLabel string) error {
|
||||
|
||||
// Return immediately if we have no certificate to use as identity
|
||||
if keyLabel == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
webConfigDir := "/etc/mqm/web/installations/Installation1/servers/mqweb"
|
||||
tls := "tls.xml"
|
||||
|
||||
tlsConfig := filepath.Join(webConfigDir, tls)
|
||||
newTLSConfig := filepath.Join(webConfigDir, tls+".tpl")
|
||||
|
||||
err := os.Remove(tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to delete file %s: %v", tlsConfig, err)
|
||||
}
|
||||
|
||||
// Symlink here to prevent issues on restart
|
||||
err = os.Symlink(newTLSConfig, tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to create symlink %s->%s: %v", newTLSConfig, tlsConfig, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigureWebKeyStore configures the Web Keystore
|
||||
func ConfigureWebKeystore(p12Truststore KeyStoreData, webKeystore string) (string, error) {
|
||||
|
||||
if webKeystore == "" {
|
||||
webKeystore = webKeystoreDefault
|
||||
}
|
||||
webKeystoreFile := filepath.Join(keystoreDir, webKeystore)
|
||||
|
||||
// Check if a new self-signed certificate should be generated
|
||||
genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME")
|
||||
if genHostName != "" {
|
||||
|
||||
// Create the Web Keystore
|
||||
newWebKeystore := keystore.NewPKCS12KeyStore(webKeystoreFile, p12Truststore.Password)
|
||||
err := newWebKeystore.Create()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to create Web Keystore %s: %v", webKeystoreFile, err)
|
||||
}
|
||||
|
||||
// Generate a new self-signed certificate in the Web Keystore
|
||||
err = newWebKeystore.CreateSelfSignedCertificate("default", fmt.Sprintf("CN=%s", genHostName), genHostName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to generate certificate in Web Keystore %s with DN of 'CN=%s': %v", webKeystoreFile, genHostName, err)
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check Web Keystore already exists
|
||||
_, err := os.Stat(webKeystoreFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to find existing Web Keystore %s: %v", webKeystoreFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check Web Truststore already exists
|
||||
_, err := os.Stat(p12Truststore.Keystore.Filename)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to find existing Web Truststore %s: %v", p12Truststore.Keystore.Filename, err)
|
||||
}
|
||||
|
||||
return webKeystore, nil
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
© Copyright IBM Corporation 2018, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -16,66 +16,26 @@ limitations under the License.
|
||||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/user"
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/command"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// User holds information on primary and supplemental OS groups
|
||||
type User struct {
|
||||
UID string
|
||||
Name string
|
||||
PrimaryGID string
|
||||
SupplementalGID []string
|
||||
UID int
|
||||
PrimaryGID int
|
||||
SupplementalGID []int
|
||||
}
|
||||
|
||||
// GetUser returns the current user and group information
|
||||
func GetUser() (User, error) {
|
||||
u, err := user.Current()
|
||||
u := User{
|
||||
UID: unix.Geteuid(),
|
||||
PrimaryGID: unix.Getgid(),
|
||||
}
|
||||
groups, err := unix.Getgroups()
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
return u, err
|
||||
}
|
||||
g, err := getCurrentUserGroups()
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
if err != nil && len(g) == 0 {
|
||||
return User{
|
||||
UID: u.Uid,
|
||||
Name: u.Name,
|
||||
PrimaryGID: u.Gid,
|
||||
SupplementalGID: []string{},
|
||||
}, nil
|
||||
}
|
||||
// Look for the primary group in the list of group IDs
|
||||
for i, v := range g {
|
||||
if v == u.Gid {
|
||||
// Remove the element from the slice
|
||||
g = append(g[:i], g[i+1:]...)
|
||||
}
|
||||
}
|
||||
return User{
|
||||
UID: u.Uid,
|
||||
Name: u.Name,
|
||||
PrimaryGID: u.Gid,
|
||||
SupplementalGID: g,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getCurrentUserGroups() ([]string, error) {
|
||||
var nilArray []string
|
||||
out, _, err := command.Run("id", "--groups")
|
||||
if err != nil {
|
||||
return nilArray, err
|
||||
}
|
||||
|
||||
out = strings.TrimSpace(out)
|
||||
if out == "" {
|
||||
return nilArray, fmt.Errorf("Unable to determine groups for current user")
|
||||
}
|
||||
|
||||
groups := strings.Split(out, " ")
|
||||
return groups, nil
|
||||
u.SupplementalGID = groups
|
||||
return u, nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Fat manifests
|
||||
=============
|
||||
|
||||
These are the fat manifests used by Docker Hub and Docker store to handle images with multiple CPU architectures.
|
||||
These are the fat manifests used by Docker Hub to handle images with multiple CPU architectures.
|
||||
|
||||
They are used in conjunction with [manifest-tool](https://github.com/estesp/manifest-tool), for example:
|
||||
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
image: ibmcom/mq:9.1.3.0
|
||||
image: ibmcom/mq:9.1.3.0-r3
|
||||
manifests:
|
||||
- image: ibmcom/mq:9.1.3.0-amd64
|
||||
- image: ibmcom/mq:9.1.3.0-r3-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcom/mq:9.1.3.0-ppc64le
|
||||
- image: ibmcom/mq:9.1.3.0-r3-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcom/mq:9.1.3.0-s390x
|
||||
- image: ibmcom/mq:9.1.3.0-r3-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
image: ibmcorp/mqadvanced-server-dev:9.1.3.0
|
||||
image: ibmcom/mq:9.1.4.0-r1
|
||||
manifests:
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-amd64
|
||||
- image: ibmcom/mq:9.1.4.0-r1-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-ppc64le
|
||||
- image: ibmcom/mq:9.1.4.0-r1-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-s390x
|
||||
- image: ibmcom/mq:9.1.4.0-r1-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2018
|
||||
# © Copyright IBM Corporation 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,18 +12,17 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
image: ibmcorp/mqadvanced-server-dev:9.1.1.0
|
||||
image: ibmcom/mq:9.1.5.0-r1
|
||||
manifests:
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-x86_64
|
||||
- image: ibmcom/mq:9.1.5.0-r1-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-ppc64le
|
||||
- image: ibmcom/mq:9.1.5.0-r1-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-s390x
|
||||
- image: ibmcom/mq:9.1.5.0-r1-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2018
|
||||
# © Copyright IBM Corporation 2018, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,18 +12,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
image: ibmcorp/mqadvanced-server-dev:9.1.0.0
|
||||
image: ibmcom/mq:9.2.0.0-r1
|
||||
manifests:
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.0.0-x86_64
|
||||
- image: ibmcom/mq:9.2.0.0-r1-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.0.0-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.0.0-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# © Copyright IBM Corporation 2018, 2019
|
||||
# © Copyright IBM Corporation 2018, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -14,15 +14,7 @@
|
||||
|
||||
image: ibmcom/mq:latest
|
||||
manifests:
|
||||
- image: ibmcom/mq:9.1.3.0-amd64
|
||||
- image: ibmcom/mq:9.2.0.0-r1-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcom/mq:9.1.3.0-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcom/mq:9.1.3.0-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
|
||||
@@ -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.2.0-UBI
|
||||
manifests:
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-UBI-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-UBI-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-UBI-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
@@ -1,29 +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.
|
||||
|
||||
image: ibmcorp/mqadvanced-server-dev:9.1.2.0
|
||||
manifests:
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-x86_64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-ppc64le
|
||||
platform:
|
||||
architecture: ppc64le
|
||||
os: linux
|
||||
- image: ibmcorp/mqadvanced-server-dev:9.1.2.0-s390x
|
||||
platform:
|
||||
architecture: s390x
|
||||
os: linux
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# RHEL-based container build
|
||||
|
||||
Build scripts for building a container image based on Red Hat Enterprise Linux (RHEL), using the [`buildah`](https://github.com/containers/buildah) tool. buildah is supported on RHEL V7.5 and greater.
|
||||
|
||||
WARNING: The code in this directory is not currently in use, pending deletion. The MQ container is now built using a Red Hat UBI image, using "podman build".
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Builds and tests the golang programs used by the MQ image.
|
||||
|
||||
set -ex
|
||||
|
||||
# Handle a GOPATH with multiple entries (just choose the first one)
|
||||
IFS=':' read -ra DIR <<< "$GOPATH"
|
||||
cd ${DIR[0]}/src/github.com/ibm-messaging/mq-container/
|
||||
|
||||
# Build and test the Go code
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
rm -f chkmqready chkmqhealthy runmqserver runmqdevserver
|
||||
|
||||
if [ "$MQDEV" = "TRUE" ]; then
|
||||
# Build and test the Go code
|
||||
go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" --tags 'mqdev' ../cmd/runmqserver/
|
||||
go build ../cmd/runmqdevserver/
|
||||
else
|
||||
go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" ../cmd/runmqserver/
|
||||
fi
|
||||
|
||||
go build ../cmd/chkmqready/
|
||||
go build ../cmd/chkmqhealthy/
|
||||
go test -v ../cmd/runmqserver/
|
||||
go test -v ../cmd/chkmqready/
|
||||
go test -v ../cmd/chkmqhealthy/
|
||||
if [ "$MQDEV" = "TRUE" ]; then
|
||||
go test -v ../cmd/runmqdevserver
|
||||
fi
|
||||
go test -v ../internal/...
|
||||
go vet ../cmd/... ../internal/...
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Run the Go build script inside the Go container, mounting the source
|
||||
# directory in
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 TAG DevModeFlag"
|
||||
exit 20
|
||||
}
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "ERROR: Invalid number of parameters"
|
||||
usage
|
||||
fi
|
||||
|
||||
readonly tag=$1
|
||||
readonly dev=$2
|
||||
|
||||
IMAGE_REVISION=${IMAGE_REVISION:="Not Applicable"}
|
||||
IMAGE_SOURCE=${IMAGE_SOURCE:="Not Applicable"}
|
||||
|
||||
# Run the build in a container
|
||||
# Note the ":Z" on the volume is to allow the container to access the files when SELinux is enabled
|
||||
# Note the "podman" network is used explicitly, to avoid problems other CNI networks (e.g. on an OpenShift node)
|
||||
podman run \
|
||||
--volume ${PWD}:/opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/:Z \
|
||||
--env IMAGE_REVISION="$IMAGE_REVISION" \
|
||||
--env IMAGE_SOURCE="$IMAGE_SOURCE" \
|
||||
--env MQDEV=${dev} \
|
||||
--user $(id -u) \
|
||||
--rm \
|
||||
--network podman \
|
||||
${tag} \
|
||||
bash -c "cd /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/ && ./mq-advanced-server-rhel/go-build.sh"
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Install one or more MQ components into a buildah container
|
||||
|
||||
set -ex
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 MQContainer MountLocation ARCHIVENAME PACKAGES"
|
||||
exit 20
|
||||
}
|
||||
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo "ERROR: Invalid number of parameters"
|
||||
usage
|
||||
fi
|
||||
|
||||
readonly ctr_mq=$1
|
||||
readonly mnt_mq=$2
|
||||
readonly archive=$3
|
||||
readonly mq_packages=$4
|
||||
readonly dir_extract=/tmp/extract
|
||||
readonly mqm_uid=888
|
||||
readonly mqm_gid=888
|
||||
|
||||
if [ ! -d ${dir_extract}/MQServer ]; then
|
||||
mkdir -p ${dir_extract}
|
||||
echo Extracting $archive
|
||||
tar -zxf $archive -C ${dir_extract}
|
||||
echo Extracting finished
|
||||
fi
|
||||
|
||||
# Accept the MQ license
|
||||
buildah run --user root --volume ${dir_extract}:/mnt/mq-download:Z $ctr_mq -- /mnt/mq-download/MQServer/mqlicense.sh -text_only -accept
|
||||
|
||||
# Install MQ
|
||||
buildah run --user root --volume ${dir_extract}:/mnt/mq-download:Z $ctr_mq -- bash -c "cd /mnt/mq-download/MQServer && rpm -ivh $mq_packages"
|
||||
|
||||
rm -rf ${dir_extract}/MQServer
|
||||
|
||||
# Remove 32-bit libraries from 64-bit container
|
||||
find $mnt_mq/opt/mqm $mnt_mq/var/mqm -type f -exec file {} \; | awk -F: '/ELF 32-bit/{print $1}' | xargs --no-run-if-empty rm -f
|
||||
|
||||
# Remove tar.gz files unpacked by RPM postinst scripts
|
||||
find $mnt_mq/opt/mqm -name '*.tar.gz' -delete
|
||||
|
||||
# Recommended: Set the default MQ installation (makes the MQ commands available on the PATH)
|
||||
buildah run $ctr_mq -- /opt/mqm/bin/setmqinst -p /opt/mqm -i
|
||||
|
||||
mkdir -p $mnt_mq/run/runmqserver
|
||||
chown ${mqm_uid}:${mqm_gid} $mnt_mq/run/runmqserver
|
||||
|
||||
# Remove the directory structure under /var/mqm which was created by the installer
|
||||
rm -rf $mnt_mq/var/mqm
|
||||
|
||||
# Create the mount point for volumes, ensuring MQ has permissions to all directories
|
||||
mkdir -p $mnt_mq/mnt/mqm
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group root $mnt_mq/mnt
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group root $mnt_mq/mnt/mqm
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group root $mnt_mq/mnt/mqm/data
|
||||
|
||||
# Create the directory for MQ configuration files
|
||||
mkdir -p /etc/mqm
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group root $mnt_mq/etc/mqm
|
||||
|
||||
# Create a symlink for /var/mqm -> /mnt/mqm/data
|
||||
buildah run --user root $ctr_mq -- ln -s /mnt/mqm/data /var/mqm
|
||||
|
||||
# Optional: Set these values for the IBM Cloud Vulnerability Report
|
||||
sed -i 's/PASS_MAX_DAYS\t99999/PASS_MAX_DAYS\t90/' $mnt_mq/etc/login.defs
|
||||
sed -i 's/PASS_MIN_DAYS\t0/PASS_MIN_DAYS\t1/' $mnt_mq/etc/login.defs
|
||||
sed -i 's/password\t\[success=1 default=ignore\]\tpam_unix\.so obscure sha512/password\t[success=1 default=ignore]\tpam_unix.so obscure sha512 minlen=8/' $mnt_mq/etc/pam.d/password-auth
|
||||
|
||||
buildah run $ctr_mq -- cp -rs /opt/mqm/licenses/ /
|
||||
@@ -1,173 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Build a RHEL image, using the buildah tool
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 ARCHIVE-NAME PACKAGES TAG VERSION MQDevFlag"
|
||||
exit 20
|
||||
}
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "ERROR: Invalid number of parameters"
|
||||
usage
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# Setup MQ server working container
|
||||
###############################################################################
|
||||
|
||||
# Use RHEL 7 minimal container (which doesn't include things like Python or Yum)
|
||||
readonly ctr_mq=$(buildah from rhel7-minimal)
|
||||
if [ -z "$ctr_mq" ]
|
||||
then
|
||||
echo "ERROR: ctr_mq is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
readonly mnt_mq=$(buildah mount $ctr_mq)
|
||||
if [ -z "$mnt_mq" ]
|
||||
then
|
||||
echo "ERROR: mnt_mq is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
readonly archive=downloads/$1
|
||||
readonly packages=$2
|
||||
readonly tag=$3
|
||||
readonly version=$4
|
||||
readonly mqdev=$5
|
||||
readonly mqm_uid=888
|
||||
readonly mqm_gid=888
|
||||
|
||||
###############################################################################
|
||||
# Install MQ server
|
||||
###############################################################################
|
||||
|
||||
microdnf_opts="--nodocs"
|
||||
# Check whether the host is registered with Red Hat
|
||||
if subscription-manager status ; then
|
||||
# Host is subscribed, but the minimal image has no enabled repos
|
||||
# Note that the "bc" package is the only one in "extras"
|
||||
microdnf_opts="${microdnf_opts} --enablerepo=rhel-7-server-rpms --enablerepo=rhel-7-server-extras-rpms"
|
||||
else
|
||||
# Use the Yum repositories configured on the host
|
||||
cp -R /etc/yum.repos.d/* ${mnt_mq}/etc/yum.repos.d/
|
||||
fi
|
||||
buildah run ${ctr_mq} -- microdnf ${microdnf_opts} install \
|
||||
bash \
|
||||
bc \
|
||||
coreutils \
|
||||
file \
|
||||
findutils \
|
||||
gawk \
|
||||
glibc-common \
|
||||
grep \
|
||||
passwd \
|
||||
procps-ng \
|
||||
sed \
|
||||
shadow-utils \
|
||||
tar \
|
||||
util-linux \
|
||||
which
|
||||
|
||||
# Install "sudo" if using MQ Advanced for Developers
|
||||
if [ "$mqdev" = "TRUE" ]; then
|
||||
buildah run ${ctr_mq} -- microdnf ${microdnf_opts} install sudo
|
||||
fi
|
||||
|
||||
# Clean up cached files
|
||||
buildah run ${ctr_mq} -- microdnf ${microdnf_opts} clean all
|
||||
rm -rf ${mnt_mq}/etc/yum.repos.d/*
|
||||
|
||||
buildah run --user root $ctr_mq -- groupadd --system --gid ${mqm_gid} mqm
|
||||
buildah run --user root $ctr_mq -- useradd --system --uid ${mqm_uid} --gid mqm --groups 0 mqm
|
||||
|
||||
# Install MQ server packages into the MQ builder image
|
||||
./mq-advanced-server-rhel/install-mq-rhel.sh ${ctr_mq} "${mnt_mq}" "${archive}" "${packages}"
|
||||
|
||||
# Create the directory for MQ configuration files
|
||||
mkdir -p ${mnt_mq}/etc/mqm
|
||||
chown ${mqm_uid}:${mqm_gid} ${mnt_mq}/etc/mqm
|
||||
|
||||
# Install the Go binaries into the image
|
||||
install --mode 0750 --owner ${mqm_uid} --group 0 ./build/runmqserver ${mnt_mq}/usr/local/bin/
|
||||
install --mode 6750 --owner ${mqm_uid} --group 0 ./build/chk* ${mnt_mq}/usr/local/bin/
|
||||
install --mode 0750 --owner ${mqm_uid} --group 0 ./NOTICES.txt ${mnt_mq}/opt/mqm/licenses/notices-container.txt
|
||||
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group 0 ${mnt_mq}/run/runmqserver
|
||||
buildah run --user root $ctr_mq -- touch /run/termination-log
|
||||
buildah run --user root $ctr_mq -- chown mqm:root /run/termination-log
|
||||
buildah run --user root $ctr_mq -- chmod 0660 /run/termination-log
|
||||
|
||||
# Copy in licenses from installed packages
|
||||
install --mode 0550 --owner root --group root ./mq-advanced-server-rhel/writePackages.sh ${mnt_mq}/usr/local/bin/writePackages
|
||||
buildah run --user root $ctr_mq -- /usr/local/bin/writePackages
|
||||
|
||||
# Copy web XML files
|
||||
cp -R web ${mnt_mq}/etc/mqm/web
|
||||
|
||||
# Make "mqm" the owner of all the config files
|
||||
chown --recursive ${mqm_uid}:${mqm_gid} ${mnt_mq}/etc/mqm/*
|
||||
chmod --recursive 0750 ${mnt_mq}/etc/mqm/*
|
||||
|
||||
###############################################################################
|
||||
# Final Buildah commands
|
||||
###############################################################################
|
||||
|
||||
if [ "$mqdev" = "TRUE" ]; then
|
||||
OSTAG="mq messaging developer"
|
||||
DISNAME="IBM MQ Advanced Server Developer Edition"
|
||||
PID="98102d16795c4263ad9ca075190a2d4d"
|
||||
else
|
||||
OSTAG="mq messaging"
|
||||
DISNAME="IBM MQ Advanced Server"
|
||||
PID="4486e8c4cc9146fd9b3ce1f14a2dfc5b"
|
||||
fi
|
||||
|
||||
buildah config \
|
||||
--port 1414/tcp \
|
||||
--port 9157/tcp \
|
||||
--port 9443/tcp \
|
||||
--os linux \
|
||||
--label architecture=amd64 \
|
||||
--label io.openshift.tags="$OSTAG" \
|
||||
--label io.k8s.display-name="$DISNAME" \
|
||||
--label io.k8s.description="IBM MQ is messaging middleware that simplifies and accelerates the integration of diverse applications and business data across multiple platforms. It uses message queues to facilitate the exchanges of information and offers a single messaging solution for cloud, mobile, Internet of Things (IoT) and on-premises environments." \
|
||||
--label name="${tag%:*}" \
|
||||
--label vendor="IBM" \
|
||||
--label version="$version" \
|
||||
--label release="1" \
|
||||
--label run="docker run -d -e LICENSE=accept --name ibm-mq ${tag%:*}" \
|
||||
--label summary="$DISNAME" \
|
||||
--label description="IBM MQ is messaging middleware that simplifies and accelerates the integration of diverse applications and business data across multiple platforms. It uses message queues to facilitate the exchanges of information and offers a single messaging solution for cloud, mobile, Internet of Things (IoT) and on-premises environments." \
|
||||
--label IBM_PRODUCT_ID="$PID" \
|
||||
--label IBM_PRODUCT_NAME="$DISNAME" \
|
||||
--label IBM_PRODUCT_VERSION="$version" \
|
||||
--env AMQ_ADDITIONAL_JSON_LOG=1 \
|
||||
--env LANG=en_US.UTF-8 \
|
||||
--env LOG_FORMAT=basic \
|
||||
--entrypoint runmqserver \
|
||||
--user ${mqm_uid} \
|
||||
$ctr_mq
|
||||
buildah unmount $ctr_mq
|
||||
buildah commit $ctr_mq $tag
|
||||
|
||||
buildah rm $ctr_mq
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Build a RHEL image for building Go programs which use MQ
|
||||
|
||||
set -ex
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 REDIST-ARCHIVE-NAME TAG"
|
||||
exit 20
|
||||
}
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "ERROR: Invalid number of parameters"
|
||||
usage
|
||||
fi
|
||||
|
||||
readonly mq_redist_archive=downloads/$1
|
||||
readonly tag=$2
|
||||
# Use Red Hat's Go toolset image as the base
|
||||
readonly ctr_mq=$(buildah from devtools/go-toolset-7-rhel7)
|
||||
if [ -z "$ctr_mq" ]
|
||||
then
|
||||
echo "ERROR: ctr_mq is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
readonly mnt_mq_go=$(buildah mount $ctr_mq)
|
||||
if [ -z "$mnt_mq_go" ]
|
||||
then
|
||||
echo "ERROR: mnt_mq_go is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
# Install the MQ redistributable client (including header files) into the Go builder image
|
||||
mkdir -p ${mnt_mq_go}/opt/mqm
|
||||
tar -xzf ${mq_redist_archive} -C ${mnt_mq_go}/opt/mqm
|
||||
|
||||
# Clean up Yum files
|
||||
rm -rf ${mnt_mq_go}/etc/yum.repos.d/*
|
||||
|
||||
buildah unmount ${ctr_mq}
|
||||
# Set environment variables for MQ/Go compilation
|
||||
buildah config \
|
||||
--os linux \
|
||||
--env CGO_CFLAGS="-I/opt/mqm/inc/" \
|
||||
--env CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" \
|
||||
${ctr_mq}
|
||||
buildah commit ${ctr_mq} ${tag}
|
||||
|
||||
buildah rm ${ctr_mq}
|
||||
@@ -1,121 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © 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.
|
||||
|
||||
# Build a RHEL image of MQ Advanced for Developers, using the buildah tool
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 BASETAG TAG VERSION"
|
||||
exit 20
|
||||
}
|
||||
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "ERROR: Invalid number of parameters"
|
||||
usage
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# Setup MQ server working container
|
||||
###############################################################################
|
||||
|
||||
# Use a "scratch" container, so the resulting image has minimal files
|
||||
# Resulting image won't have yum, for example
|
||||
readonly basetag=$1
|
||||
readonly ctr_mq=$(buildah from $basetag)
|
||||
if [ -z "$ctr_mq" ]
|
||||
then
|
||||
echo "ERROR: ctr_mq is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
readonly mnt_mq=$(buildah mount $ctr_mq)
|
||||
if [ -z "$mnt_mq" ]
|
||||
then
|
||||
echo "ERROR: mnt_mq is empty. Check above output for errors"
|
||||
exit 50
|
||||
fi
|
||||
|
||||
readonly tag=$2
|
||||
readonly version=$3
|
||||
readonly mqm_uid=888
|
||||
readonly mqm_gid=888
|
||||
|
||||
# WARNING: This is what allows the mqm user to change the password of any other user
|
||||
# It's used by runmqdevserver to change the admin/app passwords.
|
||||
echo "mqm ALL = NOPASSWD: /usr/sbin/chpasswd" > $mnt_mq/etc/sudoers.d/mq-dev-config
|
||||
|
||||
# Run these commands inside the container so that the SELinux context is handled correctly
|
||||
buildah run --user root $ctr_mq -- useradd --gid mqm admin
|
||||
buildah run --user root $ctr_mq -- groupadd --system mqclient
|
||||
buildah run --user root $ctr_mq -- useradd --gid mqclient app
|
||||
buildah run --user root $ctr_mq -- bash -c "echo admin:passw0rd | chpasswd"
|
||||
|
||||
mkdir --parents $mnt_mq/run/runmqdevserver
|
||||
chown ${mqm_uid}:${mqm_gid} $mnt_mq/run/runmqdevserver
|
||||
|
||||
# Copy runmqdevserver program
|
||||
install --mode 0750 --owner ${mqm_uid} --group ${mqm_gid} ./build/runmqdevserver ${mnt_mq}/usr/local/bin/
|
||||
|
||||
install --directory --mode 0775 --owner ${mqm_uid} --group 0 ${mnt_mq}/run/runmqdevserver
|
||||
|
||||
# Copy template files
|
||||
cp ./incubating/mqadvanced-server-dev/*.tpl ${mnt_mq}/etc/mqm/
|
||||
|
||||
# Copy web XML files for default developer configuration
|
||||
cp -R incubating/mqadvanced-server-dev/web/ ${mnt_mq}/etc/mqm/web
|
||||
|
||||
# Make "mqm" the owner of all the config files
|
||||
chown --recursive ${mqm_uid}:${mqm_gid} ${mnt_mq}/etc/mqm/*
|
||||
chmod --recursive 0750 ${mnt_mq}/etc/mqm/*
|
||||
|
||||
###############################################################################
|
||||
# Final Buildah commands
|
||||
###############################################################################
|
||||
|
||||
buildah config \
|
||||
--port 1414/tcp \
|
||||
--port 9157/tcp \
|
||||
--port 9443/tcp \
|
||||
--os linux \
|
||||
--label architecture=amd64 \
|
||||
--label io.openshift.tags="mq messaging developer" \
|
||||
--label io.k8s.display-name="IBM MQ Advanced Server Developer Edition" \
|
||||
--label io.k8s.description="IBM MQ is messaging middleware that simplifies and accelerates the integration of diverse applications and business data across multiple platforms. It uses message queues to facilitate the exchanges of information and offers a single messaging solution for cloud, mobile, Internet of Things (IoT) and on-premises environments." \
|
||||
--label name="${tag%:*}" \
|
||||
--label vendor="IBM" \
|
||||
--label version="$version" \
|
||||
--label release="1" \
|
||||
--label run="docker run -d -e LICENSE=accept --name ibm-mq-dev ${tag%:*}" \
|
||||
--label summary="IBM MQ Advanced Server Developer Edition" \
|
||||
--label description="IBM MQ is messaging middleware that simplifies and accelerates the integration of diverse applications and business data across multiple platforms. It uses message queues to facilitate the exchanges of information and offers a single messaging solution for cloud, mobile, Internet of Things (IoT) and on-premises environments." \
|
||||
--label IBM_PRODUCT_ID="98102d16795c4263ad9ca075190a2d4d" \
|
||||
--label IBM_PRODUCT_NAME="IBM MQ Advanced Server Developer Edition" \
|
||||
--label IBM_PRODUCT_VERSION="$version" \
|
||||
--env AMQ_ADDITIONAL_JSON_LOG=1 \
|
||||
--env LANG=en_US.UTF-8 \
|
||||
--env LOG_FORMAT=basic \
|
||||
--env MQ_ADMIN_PASSWORD=passw0rd \
|
||||
--env MQ_DEV=true \
|
||||
--entrypoint runmqdevserver \
|
||||
--user ${mqm_uid} \
|
||||
$ctr_mq
|
||||
buildah unmount $ctr_mq
|
||||
buildah commit $ctr_mq $tag
|
||||
|
||||
buildah rm $ctr_mq
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/containerruntime"
|
||||
"github.com/ibm-messaging/mq-container/internal/logger"
|
||||
"github.com/ibm-messaging/mq-container/internal/user"
|
||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||
)
|
||||
|
||||
// LogContainerDetails logs details about the container runtime
|
||||
@@ -45,11 +45,14 @@ func LogContainerDetails(log *logger.Logger) error {
|
||||
log.Printf("Base image: %v", bi)
|
||||
}
|
||||
u, err := user.GetUser()
|
||||
if err != nil {
|
||||
log.Printf("Error: %v\nUser:\n uid: %v\n gid: %v\n supGid: %v", err, u.UID, u.PrimaryGID, u.SupplementalGID)
|
||||
}
|
||||
if err == nil {
|
||||
if len(u.SupplementalGID) == 0 {
|
||||
log.Printf("Running as user ID %v (%v) with primary group %v", u.UID, u.Name, u.PrimaryGID)
|
||||
log.Printf("Running as user ID %v with primary group %v", u.UID, u.PrimaryGID)
|
||||
} else {
|
||||
log.Printf("Running as user ID %v (%v) with primary group %v, and supplementary groups %v", u.UID, u.Name, u.PrimaryGID, strings.Join(u.SupplementalGID, ","))
|
||||
log.Printf("Running as user ID %v with primary group %v, and supplementary groups %v", u.UID, u.PrimaryGID, strings.Trim(strings.Join(strings.Fields(fmt.Sprint(u.SupplementalGID)), ","), "[]"))
|
||||
}
|
||||
}
|
||||
caps, err := containerruntime.GetCapabilities()
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ package mqini
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -60,6 +62,11 @@ func getQueueManagerFromStanza(stanza string) (*QueueManager, error) {
|
||||
|
||||
// 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 {
|
||||
@@ -71,8 +78,15 @@ func GetQueueManager(name string) (*QueueManager, error) {
|
||||
// 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")
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2018
|
||||
© Copyright IBM Corporation 2018, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -1,19 +0,0 @@
|
||||
* © Copyright IBM Corporation 2017
|
||||
*
|
||||
* 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.
|
||||
|
||||
DEFINE CHANNEL(PASSWORD.SVRCONN) CHLTYPE(SVRCONN) REPLACE
|
||||
SET CHLAUTH(PASSWORD.SVRCONN) TYPE(BLOCKUSER) USERLIST('nobody') DESCR('Allow privileged users on this channel')
|
||||
SET CHLAUTH('*') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(NOACCESS) DESCR('BackStop rule')
|
||||
SET CHLAUTH(PASSWORD.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(REQUIRED)
|
||||
ALTER AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) ADOPTCTX(YES)
|
||||
@@ -1,15 +0,0 @@
|
||||
* © Copyright IBM Corporation 2017
|
||||
*
|
||||
* 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.
|
||||
|
||||
REFRESH SECURITY TYPE(CONNAUTH)
|
||||
@@ -81,8 +81,6 @@ func TestDevSecure(t *testing.T) {
|
||||
"LICENSE=accept",
|
||||
"MQ_QMGR_NAME=" + qm,
|
||||
"MQ_APP_PASSWORD=" + appPassword,
|
||||
"MQ_TLS_KEYSTORE=/var/tls/server.p12",
|
||||
"MQ_TLS_PASSPHRASE=" + tlsPassPhrase,
|
||||
"DEBUG=1",
|
||||
},
|
||||
Image: imageName(),
|
||||
@@ -90,7 +88,7 @@ func TestDevSecure(t *testing.T) {
|
||||
hostConfig := container.HostConfig{
|
||||
Binds: []string{
|
||||
coverageBind(t),
|
||||
tlsDir(t, false) + ":/var/tls",
|
||||
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
|
||||
},
|
||||
// Assign a random port for the web server on the host
|
||||
// TODO: Don't do this for all tests
|
||||
@@ -145,7 +143,7 @@ func TestDevWebDisabled(t *testing.T) {
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
t.Run("Web", func(t *testing.T) {
|
||||
_, dspmqweb := execContainer(t, cli, id, "mqm", []string{"dspmqweb"})
|
||||
_, dspmqweb := execContainer(t, cli, id, "", []string{"dspmqweb"})
|
||||
if !strings.Contains(dspmqweb, "Server mqweb is not running.") && !strings.Contains(dspmqweb, "MQWB1125I") {
|
||||
t.Errorf("Expected dspmqweb to say 'Server is not running' or 'MQWB1125I'; got \"%v\"", dspmqweb)
|
||||
}
|
||||
@@ -176,7 +174,7 @@ func TestDevConfigDisabled(t *testing.T) {
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
waitForWebReady(t, cli, id, insecureTLSConfig)
|
||||
rc, _ := execContainer(t, cli, id, "mqm", []string{"bash", "-c", "echo 'display qlocal(DEV*)' | runmqsc"})
|
||||
rc, _ := execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'display qlocal(DEV*)' | runmqsc"})
|
||||
if rc == 0 {
|
||||
t.Errorf("Expected DEV queues to be missing")
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func tlsDir(t *testing.T, unixPath bool) string {
|
||||
// runJMSTests runs a container with a JMS client, which connects to the queue manager container with the specified ID
|
||||
func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, password string) {
|
||||
containerConfig := container.Config{
|
||||
// -e MQ_PORT_1414_TCP_ADDR=9.145.14.173 -e MQ_USERNAME=app -e MQ_PASSWORD=passw0rd -e MQ_CHANNEL=DEV.APP.SVRCONN -e MQ_TLS_KEYSTORE=/tls/test.p12 -e MQ_TLS_PASSPHRASE=passw0rd -v /Users/arthurbarr/go/src/github.com/ibm-messaging/mq-container/test/tls:/tls msgtest
|
||||
// -e MQ_PORT_1414_TCP_ADDR=9.145.14.173 -e MQ_USERNAME=app -e MQ_PASSWORD=passw0rd -e MQ_CHANNEL=DEV.APP.SVRCONN -e MQ_TLS_TRUSTSTORE=/tls/test.p12 -e MQ_TLS_PASSPHRASE=passw0rd -v /Users/arthurbarr/go/src/github.com/ibm-messaging/mq-container/test/tls:/tls msgtest
|
||||
Env: []string{
|
||||
"MQ_PORT_1414_TCP_ADDR=" + getIPAddress(t, cli, ID),
|
||||
"MQ_USERNAME=" + user,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -75,6 +75,29 @@ func TestLicenseView(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
//Start a container with qm grace set to x seconds
|
||||
//Check that when the container is stopped that the command endmqm has option -tp and x
|
||||
func TestEndMQMOpts(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
containerConfig := container.Config{
|
||||
Env: []string{"LICENSE=accept", "MQ_GRACE_PERIOD=27"},
|
||||
}
|
||||
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
killContainer(t, cli, id, "SIGTERM")
|
||||
_, out := execContainer(t, cli, id, "", []string{"bash", "-c", "ps -ef | grep 'endmqm -w -r -tp 27'"})
|
||||
t.Log(out)
|
||||
if !strings.Contains(out, "endmqm -w -r -tp 27") {
|
||||
t.Errorf("Expected endmqm options endmqm -w -r -tp 27; got \"%v\"", out)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGoldenPath starts a queue manager successfully when metrics are enabled
|
||||
func TestGoldenPathWithMetrics(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -159,7 +182,7 @@ func utilTestNoQueueManagerName(t *testing.T, hostName string, expectedName stri
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
_, out := execContainer(t, cli, id, "mqm", []string{"dspmq"})
|
||||
_, out := execContainer(t, cli, id, "", []string{"dspmq"})
|
||||
if !strings.Contains(out, search) {
|
||||
t.Errorf("Expected result of running dspmq to contain name=%v, got name=%v", search, out)
|
||||
}
|
||||
@@ -391,9 +414,7 @@ func TestCreateQueueManagerFail(t *testing.T) {
|
||||
FROM %v
|
||||
USER root
|
||||
RUN echo '#!/bin/bash\nexit 999' > /opt/mqm/bin/crtmqm
|
||||
RUN chown mqm:mqm /opt/mqm/bin/crtmqm
|
||||
RUN chmod 6550 /opt/mqm/bin/crtmqm
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
defer deleteImage(t, cli, tag)
|
||||
@@ -426,9 +447,7 @@ func TestStartQueueManagerFail(t *testing.T) {
|
||||
FROM %v
|
||||
USER root
|
||||
RUN echo '#!/bin/bash\ndltmqm $@ && strmqm $@' > /opt/mqm/bin/strmqm
|
||||
RUN chown mqm:mqm /opt/mqm/bin/strmqm
|
||||
RUN chmod 6550 /opt/mqm/bin/strmqm
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
defer deleteImage(t, cli, tag)
|
||||
@@ -487,12 +506,12 @@ func TestVolumeUnmount(t *testing.T) {
|
||||
t.Fatalf("Expected umount to work with rc=0, got %v. Output was: %s", rc, out)
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
rc, _ = execContainer(t, cli, ctr.ID, "mqm", []string{"chkmqhealthy"})
|
||||
rc, _ = execContainer(t, cli, ctr.ID, "", []string{"chkmqhealthy"})
|
||||
if rc == 0 {
|
||||
t.Errorf("Expected chkmqhealthy to fail")
|
||||
_, df := execContainer(t, cli, ctr.ID, "mqm", []string{"df"})
|
||||
_, df := execContainer(t, cli, ctr.ID, "", []string{"df"})
|
||||
t.Logf(df)
|
||||
_, ps := execContainer(t, cli, ctr.ID, "mqm", []string{"ps", "-ef"})
|
||||
_, ps := execContainer(t, cli, ctr.ID, "", []string{"ps", "-ef"})
|
||||
t.Logf(ps)
|
||||
}
|
||||
}
|
||||
@@ -518,14 +537,14 @@ func TestZombies(t *testing.T) {
|
||||
waitForReady(t, cli, id)
|
||||
// Kill an MQ process with children. After it is killed, its children
|
||||
// will be adopted by PID 1, and should then be reaped when they die.
|
||||
_, out := execContainer(t, cli, id, "mqm", []string{"pkill", "--signal", "kill", "-c", "amqzxma0"})
|
||||
_, out := execContainer(t, cli, id, "", []string{"pkill", "--signal", "kill", "-c", "amqzxma0"})
|
||||
if out == "0" {
|
||||
t.Log("Failed to kill process 'amqzxma0'")
|
||||
_, out := execContainer(t, cli, id, "root", []string{"ps", "-lA"})
|
||||
_, out := execContainer(t, cli, id, "", []string{"ps", "-lA"})
|
||||
t.Fatalf("Here is a list of currently running processes:\n%s", out)
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
_, out = execContainer(t, cli, id, "mqm", []string{"bash", "-c", "ps -lA | grep '^. Z'"})
|
||||
_, out = execContainer(t, cli, id, "", []string{"bash", "-c", "ps -lA | grep '^. Z'"})
|
||||
if out != "" {
|
||||
count := strings.Count(out, "\n") + 1
|
||||
t.Errorf("Expected zombies=0, got %v", count)
|
||||
@@ -552,7 +571,7 @@ func TestMQSC(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD test.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"test.mqsc", "DEFINE QLOCAL(test)"},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -565,7 +584,16 @@ func TestMQSC(t *testing.T) {
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
rc, mqscOutput := execContainer(t, cli, id, "mqm", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test)' | runmqsc"})
|
||||
|
||||
rc := -1
|
||||
mqscOutput := ""
|
||||
for i := 0; i < 60; i++ {
|
||||
rc, mqscOutput = execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test)' | runmqsc"})
|
||||
if rc == 0 {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
if rc != 0 {
|
||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
||||
t.Fatalf("Expected runmqsc to exit with rc=0, got %v with error %v", rc, r.FindString(mqscOutput))
|
||||
@@ -595,7 +623,7 @@ func TestLargeMQSC(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD test.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"test.mqsc", buf.String()},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -609,7 +637,15 @@ func TestLargeMQSC(t *testing.T) {
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
|
||||
rc, mqscOutput := execContainer(t, cli, id, "mqm", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test" + strconv.Itoa(numQueues) + ")' | runmqsc"})
|
||||
rc := -1
|
||||
mqscOutput := ""
|
||||
for i := 0; i < 60; i++ {
|
||||
rc, mqscOutput = execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test" + strconv.Itoa(numQueues) + ")' | runmqsc"})
|
||||
if rc == 0 {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
if rc != 0 {
|
||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
||||
t.Fatalf("Expected runmqsc to exit with rc=0, got %v with error %v", rc, r.FindString(mqscOutput))
|
||||
@@ -667,7 +703,7 @@ func TestRedactValidMQSC(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD test.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"test.mqsc", buf.String()},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -739,7 +775,7 @@ func TestRedactInvalidMQSC(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD test.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"test.mqsc", buf.String()},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -785,7 +821,7 @@ func TestInvalidMQSC(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD mqscTest.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/mqscTest.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"mqscTest.mqsc", "DEFINE INVALIDLISTENER('TEST.LISTENER.TCP') TRPTYPE(TCP) PORT(1414) CONTROL(QMGR) REPLACE"},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -804,6 +840,187 @@ func TestInvalidMQSC(t *testing.T) {
|
||||
expectTerminationMessage(t, cli, id)
|
||||
}
|
||||
|
||||
func TestSimpleMQIniMerge(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var files = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"Dockerfile", fmt.Sprintf(`
|
||||
FROM %v
|
||||
USER root
|
||||
ADD test1.ini /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test1.ini
|
||||
USER 1001`, imageName())},
|
||||
{"test1.ini",
|
||||
"Log:\n LogSecondaryFiles=28"},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
defer deleteImage(t, cli, tag)
|
||||
|
||||
containerConfig := container.Config{
|
||||
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||
Image: tag,
|
||||
}
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
|
||||
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||
_, test := execContainer(t, cli, id, "", []string{"bash", "-c", catIniFileCommand})
|
||||
merged := strings.Contains(test, "LogSecondaryFiles=28")
|
||||
|
||||
if !merged {
|
||||
t.Error("ERROR: The Files are not merged correctly")
|
||||
}
|
||||
|
||||
}
|
||||
func TestMultipleIniMerge(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var files = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"Dockerfile", fmt.Sprintf(`
|
||||
FROM %v
|
||||
USER root
|
||||
ADD test1.ini /etc/mqm/
|
||||
ADD test2.ini /etc/mqm/
|
||||
ADD test3.ini /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test1.ini
|
||||
RUN chmod 0660 /etc/mqm/test2.ini
|
||||
RUN chmod 0660 /etc/mqm/test3.ini
|
||||
USER 1001`, imageName())},
|
||||
{"test1.ini",
|
||||
"Log:\n LogSecondaryFiles=28"},
|
||||
{"test2.ini",
|
||||
"Log:\n LogSecondaryFiles=28"},
|
||||
{"test3.ini",
|
||||
"ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF"},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
defer deleteImage(t, cli, tag)
|
||||
|
||||
containerConfig := container.Config{
|
||||
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||
Image: tag,
|
||||
}
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
|
||||
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||
_, test := execContainer(t, cli, id, "", []string{"bash", "-c", catIniFileCommand})
|
||||
|
||||
//checks that no duplicates are created by adding 2 ini files with the same line
|
||||
numberOfDuplicates := strings.Count(test, "LogSecondaryFiles=28")
|
||||
|
||||
newStanza := strings.Contains(test, "ApplicationTrace:\n ApplName=amqsact*")
|
||||
|
||||
if (numberOfDuplicates > 1) || !newStanza {
|
||||
t.Error("ERROR: The Files are not merged correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMQIniMergeOnTheSameVolumeButTwoContainers(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var filesFirstContainer = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"Dockerfile", fmt.Sprintf(`
|
||||
FROM %v
|
||||
USER root
|
||||
ADD test1.ini /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test1.ini
|
||||
USER 1001`, imageName())},
|
||||
{"test1.ini",
|
||||
"ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF"},
|
||||
}
|
||||
firstImage := createImage(t, cli, filesFirstContainer)
|
||||
defer deleteImage(t, cli, firstImage)
|
||||
vol := createVolume(t, cli, t.Name())
|
||||
defer removeVolume(t, cli, vol.Name)
|
||||
|
||||
containerConfig := container.Config{
|
||||
Image: firstImage,
|
||||
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||
}
|
||||
|
||||
hostConfig := container.HostConfig{
|
||||
Binds: []string{
|
||||
coverageBind(t),
|
||||
vol.Name + ":/mnt/mqm",
|
||||
},
|
||||
}
|
||||
networkingConfig := network.NetworkingConfig{}
|
||||
ctr1, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
startContainer(t, cli, ctr1.ID)
|
||||
waitForReady(t, cli, ctr1.ID)
|
||||
|
||||
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/qm1/qm.ini")
|
||||
_, test := execContainer(t, cli, ctr1.ID, "", []string{"bash", "-c", catIniFileCommand})
|
||||
addedStanza := strings.Contains(test, "ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF")
|
||||
|
||||
if addedStanza != true {
|
||||
t.Error("ERROR: The Files are not merged correctly")
|
||||
}
|
||||
// Delete the first container
|
||||
cleanContainer(t, cli, ctr1.ID)
|
||||
|
||||
var filesSecondContainer = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"Dockerfile", fmt.Sprintf(`
|
||||
FROM %v
|
||||
USER root
|
||||
ADD test1.ini /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test1.ini
|
||||
USER 1001`, imageName())},
|
||||
{"test1.ini",
|
||||
"Log:\n LogFilePages=5000"},
|
||||
}
|
||||
|
||||
secondImage := createImage(t, cli, filesSecondContainer)
|
||||
defer deleteImage(t, cli, secondImage)
|
||||
|
||||
containerConfig2 := container.Config{
|
||||
Image: secondImage,
|
||||
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||
}
|
||||
|
||||
ctr2, err := cli.ContainerCreate(context.Background(), &containerConfig2, &hostConfig, &networkingConfig, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanContainer(t, cli, ctr2.ID)
|
||||
startContainer(t, cli, ctr2.ID)
|
||||
waitForReady(t, cli, ctr2.ID)
|
||||
|
||||
_, test2 := execContainer(t, cli, ctr2.ID, "", []string{"bash", "-c", catIniFileCommand})
|
||||
changedStanza := strings.Contains(test2, "LogFilePages=5000")
|
||||
//check if stanza that was merged in the first container doesnt exist in this one.
|
||||
firstMergedStanza := strings.Contains(test2, "ApplicationTrace:\n ApplName=amqsact*\n Trace=OFF")
|
||||
|
||||
if !changedStanza || firstMergedStanza {
|
||||
t.Error("ERROR: The Files are not merged correctly after removing first container")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestReadiness creates a new image with large amounts of MQSC in, to
|
||||
// ensure that the readiness check doesn't pass until configuration has finished.
|
||||
// WARNING: This test is sensitive to the speed of the machine it's running on.
|
||||
@@ -828,7 +1045,7 @@ func TestReadiness(t *testing.T) {
|
||||
RUN rm -f /etc/mqm/*.mqsc
|
||||
ADD test.mqsc /etc/mqm/
|
||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||
USER mqm`, imageName())},
|
||||
USER 1001`, imageName())},
|
||||
{"test.mqsc", buf.String()},
|
||||
}
|
||||
tag := createImage(t, cli, files)
|
||||
@@ -841,20 +1058,27 @@ func TestReadiness(t *testing.T) {
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
queueCheckCommand := fmt.Sprintf("echo 'DISPLAY QLOCAL(test%v)' | runmqsc", numQueues)
|
||||
_, mqsc := execContainer(t, cli, id, "root", []string{"cat", "/etc/mqm/test.mqsc"})
|
||||
_, mqsc := execContainer(t, cli, id, "", []string{"cat", "/etc/mqm/test.mqsc"})
|
||||
t.Log(mqsc)
|
||||
for {
|
||||
readyRC, _ := execContainer(t, cli, id, "mqm", []string{"chkmqready"})
|
||||
queueCheckRC, queueCheckOut := execContainer(t, cli, id, "mqm", []string{"bash", "-c", queueCheckCommand})
|
||||
t.Logf("readyRC=%v,queueCheckRC=%v\n", readyRC, queueCheckRC)
|
||||
|
||||
readyRC, _ := execContainer(t, cli, id, "", []string{"chkmqready"})
|
||||
if readyRC == 0 {
|
||||
queueCheckRC := -1
|
||||
queueCheckOut := ""
|
||||
for i := 1; i < 60; i++ {
|
||||
queueCheckRC, queueCheckOut = execContainer(t, cli, id, "", []string{"bash", "-c", queueCheckCommand})
|
||||
t.Logf("readyRC=%v,queueCheckRC=%v\n", readyRC, queueCheckRC)
|
||||
if queueCheckRC == 0 {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
if queueCheckRC != 0 {
|
||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
||||
t.Fatalf("Runmqsc returned %v with error %v. chkmqready returned %v when MQSC had not finished", queueCheckRC, r.FindString(queueCheckOut), readyRC)
|
||||
} else {
|
||||
// chkmqready says OK, and the last queue exists, so return
|
||||
_, runmqsc := execContainer(t, cli, id, "root", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test1)' | runmqsc"})
|
||||
_, runmqsc := execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test1)' | runmqsc"})
|
||||
t.Log(runmqsc)
|
||||
return
|
||||
}
|
||||
@@ -903,7 +1127,7 @@ func TestErrorLogRotation(t *testing.T) {
|
||||
for {
|
||||
execContainer(t, cli, id, "fred", []string{"bash", "-c", "/opt/mqm/samp/bin/amqsput FAKE"})
|
||||
|
||||
_, atoiStr := execContainer(t, cli, id, "mqm", []string{"bash", "-c", "wc -c < " + filepath.Join(dir, "AMQERR02.json")})
|
||||
_, atoiStr := execContainer(t, cli, id, "", []string{"bash", "-c", "wc -c < " + filepath.Join(dir, "AMQERR02.json")})
|
||||
amqerr02size, _ := strconv.Atoi(atoiStr)
|
||||
|
||||
if amqerr02size > 0 {
|
||||
@@ -911,7 +1135,7 @@ func TestErrorLogRotation(t *testing.T) {
|
||||
break
|
||||
}
|
||||
}
|
||||
_, out := execContainer(t, cli, id, "root", []string{"ls", "-l", dir})
|
||||
_, out := execContainer(t, cli, id, "", []string{"ls", "-l", dir})
|
||||
t.Log(out)
|
||||
stopContainer(t, cli, id)
|
||||
b := copyFromContainer(t, cli, id, filepath.Join(dir, "AMQERR01.json"))
|
||||
@@ -1055,7 +1279,7 @@ func TestCorrectLicense(t *testing.T) {
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
|
||||
rc, license := execContainer(t, cli, id, "mqm", []string{"dspmqver", "-f", "8192", "-b"})
|
||||
rc, license := execContainer(t, cli, id, "", []string{"dspmqver", "-f", "8192", "-b"})
|
||||
if rc != 0 {
|
||||
t.Fatalf("Failed to get license string. RC=%d. Output=%s", rc, license)
|
||||
}
|
||||
@@ -1185,3 +1409,68 @@ func TestVersioning(t *testing.T) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestTraceStrmqm(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
containerConfig := container.Config{
|
||||
Env: []string{
|
||||
"LICENSE=accept",
|
||||
"MQ_ENABLE_TRACE_STRMQM=1",
|
||||
},
|
||||
}
|
||||
id := runContainer(t, cli, &containerConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
|
||||
rc, _ := execContainer(t, cli, id, "", []string{"bash", "-c", "ls -A /var/mqm/trace | grep .TRC"})
|
||||
if rc != 0 {
|
||||
t.Fatalf("No trace files found in trace directory /var/mqm/trace. RC=%d.", rc)
|
||||
}
|
||||
}
|
||||
|
||||
// utilTestHealthCheck is used by TestHealthCheck* to run a container with
|
||||
// privileges enabled or disabled. Otherwise the same as the golden path tests.
|
||||
func utilTestHealthCheck(t *testing.T, nonewpriv bool) {
|
||||
t.Parallel()
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
containerConfig := container.Config{
|
||||
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
|
||||
}
|
||||
hostConfig := getDefaultHostConfig(t, cli)
|
||||
hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, fmt.Sprintf("no-new-privileges:%v", nonewpriv))
|
||||
id := runContainerWithHostConfig(t, cli, &containerConfig, hostConfig)
|
||||
defer cleanContainer(t, cli, id)
|
||||
waitForReady(t, cli, id)
|
||||
rc, out := execContainer(t, cli, id, "", []string{"chkmqhealthy"})
|
||||
t.Log(out)
|
||||
if rc != 0 {
|
||||
t.Errorf("Expected chkmqhealthy to return with exit code 0; got \"%v\"", rc)
|
||||
t.Logf("Output from chkmqhealthy:\n%v", out)
|
||||
}
|
||||
// Stop the container cleanly
|
||||
stopContainer(t, cli, id)
|
||||
}
|
||||
|
||||
// TestHealthCheckWithNoNewPrivileges tests golden path start/stop plus
|
||||
// chkmqhealthy, when running in a container where no new privileges are
|
||||
// allowed (i.e. setuid is disabled)
|
||||
func TestHealthCheckWithNoNewPrivileges(t *testing.T) {
|
||||
utilTestHealthCheck(t, true)
|
||||
}
|
||||
|
||||
// TestHealthCheckWithNoNewPrivileges tests golden path start/stop plus
|
||||
// chkmqhealthy when running in a container where new privileges are
|
||||
// allowed (i.e. setuid is allowed)
|
||||
// See https://github.com/ibm-messaging/mq-container/issues/428
|
||||
func TestHealthCheckWithNewPrivileges(t *testing.T) {
|
||||
utilTestHealthCheck(t, false)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017, 2019
|
||||
© Copyright IBM Corporation 2017, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -259,20 +260,15 @@ func cleanContainer(t *testing.T, cli *client.Client, ID string) {
|
||||
}
|
||||
}
|
||||
|
||||
// runContainerWithPorts creates and starts a container, exposing the specified ports on the host.
|
||||
// If no image is specified in the container config, then the image name is retrieved from the TEST_IMAGE
|
||||
// environment variable.
|
||||
func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *container.Config, ports []int) string {
|
||||
if containerConfig.Image == "" {
|
||||
containerConfig.Image = imageName()
|
||||
}
|
||||
// Always run as the "mqm" user, unless the test has specified otherwise
|
||||
if containerConfig.User == "" {
|
||||
containerConfig.User = "mqm"
|
||||
}
|
||||
// if coverage
|
||||
containerConfig.Env = append(containerConfig.Env, "COVERAGE_FILE="+t.Name()+".cov")
|
||||
containerConfig.Env = append(containerConfig.Env, "EXIT_CODE_FILE="+getExitCodeFilename(t))
|
||||
func generateRandomUID() string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
min := 1000
|
||||
max := 9999
|
||||
return fmt.Sprint(rand.Intn(max-min) + min)
|
||||
}
|
||||
|
||||
// getDefaultHostConfig creates a HostConfig and populates it with the defaults used in testing
|
||||
func getDefaultHostConfig(t *testing.T, cli *client.Client) *container.HostConfig {
|
||||
hostConfig := container.HostConfig{
|
||||
Binds: []string{
|
||||
coverageBind(t),
|
||||
@@ -281,15 +277,9 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
||||
CapDrop: []string{
|
||||
"ALL",
|
||||
},
|
||||
Privileged: false,
|
||||
}
|
||||
if devImage(t, cli) {
|
||||
t.Logf("Detected MQ Advanced for Developers image — adding extra Linux capabilities to container")
|
||||
hostConfig.CapAdd = []string{
|
||||
"CHOWN",
|
||||
"SETUID",
|
||||
"SETGID",
|
||||
"AUDIT_WRITE",
|
||||
}
|
||||
// Only needed for a RHEL-based image
|
||||
if baseImage(t, cli) != "ubuntu" {
|
||||
hostConfig.CapAdd = append(hostConfig.CapAdd, "DAC_OVERRIDE")
|
||||
@@ -297,6 +287,37 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
||||
} else {
|
||||
t.Logf("Detected MQ Advanced image - dropping all capabilities")
|
||||
}
|
||||
return &hostConfig
|
||||
}
|
||||
|
||||
// runContainerWithHostConfig creates and starts a container, using the supplied HostConfig.
|
||||
// Note that a default HostConfig can be created using getDefaultHostConfig.
|
||||
func runContainerWithHostConfig(t *testing.T, cli *client.Client, containerConfig *container.Config, hostConfig *container.HostConfig) string {
|
||||
if containerConfig.Image == "" {
|
||||
containerConfig.Image = imageName()
|
||||
}
|
||||
// Always run as a random user, unless the test has specified otherwise
|
||||
if containerConfig.User == "" {
|
||||
containerConfig.User = generateRandomUID()
|
||||
}
|
||||
// if coverage
|
||||
containerConfig.Env = append(containerConfig.Env, "COVERAGE_FILE="+t.Name()+".cov")
|
||||
containerConfig.Env = append(containerConfig.Env, "EXIT_CODE_FILE="+getExitCodeFilename(t))
|
||||
networkingConfig := network.NetworkingConfig{}
|
||||
t.Logf("Running container (%s)", containerConfig.Image)
|
||||
ctr, err := cli.ContainerCreate(context.Background(), containerConfig, hostConfig, &networkingConfig, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
startContainer(t, cli, ctr.ID)
|
||||
return ctr.ID
|
||||
}
|
||||
|
||||
// runContainerWithPorts creates and starts a container, exposing the specified ports on the host.
|
||||
// If no image is specified in the container config, then the image name is retrieved from the TEST_IMAGE
|
||||
// environment variable.
|
||||
func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *container.Config, ports []int) string {
|
||||
hostConfig := getDefaultHostConfig(t, cli)
|
||||
for _, p := range ports {
|
||||
port := nat.Port(fmt.Sprintf("%v/tcp", p))
|
||||
hostConfig.PortBindings[port] = []nat.PortBinding{
|
||||
@@ -305,14 +326,7 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
||||
},
|
||||
}
|
||||
}
|
||||
networkingConfig := network.NetworkingConfig{}
|
||||
t.Logf("Running container (%s)", containerConfig.Image)
|
||||
ctr, err := cli.ContainerCreate(context.Background(), containerConfig, &hostConfig, &networkingConfig, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
startContainer(t, cli, ctr.ID)
|
||||
return ctr.ID
|
||||
return runContainerWithHostConfig(t, cli, containerConfig, hostConfig)
|
||||
}
|
||||
|
||||
// runContainer creates and starts a container. If no image is specified in
|
||||
@@ -380,6 +394,78 @@ func runContainerOneShotWithVolume(t *testing.T, cli *client.Client, bind string
|
||||
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) {
|
||||
t.Logf("Starting container: %v", ID)
|
||||
startOptions := types.ContainerStartOptions{}
|
||||
@@ -452,6 +538,7 @@ func waitForContainer(t *testing.T, cli *client.Client, ID string, timeout time.
|
||||
|
||||
// execContainer runs a command in a running container, and returns the exit code and output
|
||||
func execContainer(t *testing.T, cli *client.Client, ID string, user string, cmd []string) (int, string) {
|
||||
t.Logf("Running command: %v", cmd)
|
||||
config := types.ExecConfig{
|
||||
User: user,
|
||||
Privileged: false,
|
||||
@@ -520,13 +607,15 @@ func execContainer(t *testing.T, cli *client.Client, ID string, user string, cmd
|
||||
}
|
||||
|
||||
func waitForReady(t *testing.T, cli *client.Client, ID string) {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(1 * time.Second):
|
||||
rc, _ := execContainer(t, cli, ID, "mqm", []string{"chkmqready"})
|
||||
rc, _ := execContainer(t, cli, ID, "", []string{"chkmqready"})
|
||||
|
||||
if rc == 0 {
|
||||
t.Log("MQ is ready")
|
||||
return
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2019
|
||||
© Copyright IBM Corporation 2019, 2020
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -19,13 +19,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
@@ -65,78 +62,6 @@ func singleMultiInstanceQueueManager(t *testing.T, cli *client.Client, qmsharedl
|
||||
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) {
|
||||
qm1aStatus := getQueueManagerStatus(t, cli, qm1aId, "QM1")
|
||||
qm1bStatus := getQueueManagerStatus(t, cli, qm1bId, "QM1")
|
||||
@@ -151,7 +76,7 @@ func getActiveStandbyQueueManager(t *testing.T, cli *client.Client, qm1aId strin
|
||||
}
|
||||
|
||||
func getQueueManagerStatus(t *testing.T, cli *client.Client, containerID string, queueManagerName string) string {
|
||||
_, dspmqOut := execContainer(t, cli, containerID, "mqm", []string{"bash", "-c", "dspmq", "-m", queueManagerName})
|
||||
_, dspmqOut := execContainer(t, cli, containerID, "", []string{"bash", "-c", "dspmq", "-m", queueManagerName})
|
||||
regex := regexp.MustCompile(`STATUS\(.*\)`)
|
||||
status := regex.FindString(dspmqOut)
|
||||
status = strings.TrimSuffix(strings.TrimPrefix(status, "STATUS("), ")")
|
||||
|
||||
@@ -286,12 +286,12 @@ func TestQMRestart(t *testing.T) {
|
||||
|
||||
// Restart just the QM (to simulate a lost connection)
|
||||
t.Log("Stopping queue manager\n")
|
||||
rc, out := execContainer(t, cli, id, "mqm", []string{"endmqm", "-w", "-r", defaultMetricQMName})
|
||||
rc, out := execContainer(t, cli, id, "", []string{"endmqm", "-w", "-r", defaultMetricQMName})
|
||||
if rc != 0 {
|
||||
t.Fatalf("Failed to stop the queue manager. rc=%d, err=%s", rc, out)
|
||||
}
|
||||
t.Log("starting queue manager\n")
|
||||
rc, out = execContainer(t, cli, id, "mqm", []string{"strmqm", defaultMetricQMName})
|
||||
rc, out = execContainer(t, cli, id, "", []string{"strmqm", defaultMetricQMName})
|
||||
if rc != 0 {
|
||||
t.Fatalf("Failed to start the queue manager. rc=%d, err=%s", rc, out)
|
||||
}
|
||||
|
||||
1
test/messaging/.gitignore
vendored
1
test/messaging/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.classpath
|
||||
.gradle
|
||||
*.class
|
||||
.project
|
||||
.settings
|
||||
bin
|
||||
|
||||
@@ -26,25 +26,25 @@ limitations under the License.
|
||||
<dependency>
|
||||
<groupId>com.ibm.mq</groupId>
|
||||
<artifactId>com.ibm.mq.allclient</artifactId>
|
||||
<version>9.0.5.0</version>
|
||||
<version>9.1.3.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.3.2</version>
|
||||
<version>5.5.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.3.2</version>
|
||||
<version>5.5.2</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-console-standalone</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<version>1.5.2</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
31
travis-build-scripts/build.sh
Executable file
31
travis-build-scripts/build.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# © Copyright IBM Corporation 2019, 2020
|
||||
#
|
||||
# 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
|
||||
if [[ "$ARCH" = "amd64" || "$ARCH" = "s390x" ]] ; 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
|
||||
fi
|
||||
90
travis-build-scripts/create-manifest-list.sh
Executable file
90
travis-build-scripts/create-manifest-list.sh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
|
||||
# © Copyright IBM Corporation 2020
|
||||
#
|
||||
# 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
|
||||
|
||||
usage="
|
||||
Usage: create-image-manifest.sh -r hyc-mq-container-team-docker-local.artifactory.swg-devops.com -n foo -i ibm-mqadvanced-server-dev -t test -d \"sha256:038ad492532b099c324b897ce9da31ae0be312a1d0063f6456f2e3143cc4f4b8 sha256:754f466cf2cfc5183ac705689ce6720f27fecd07c97970ba3ec48769acba067d\"
|
||||
|
||||
Where:
|
||||
-r - The image registry hostname
|
||||
-n - The image registry namespace
|
||||
-i - The image name
|
||||
-t - The desired top level manifest tag
|
||||
-d - A space separated list of sha256 image digests to be included
|
||||
"
|
||||
|
||||
GREEN="\033[32m"
|
||||
RED="\033[31m"
|
||||
BLUE="\033[34m"
|
||||
PURPLE="\033[35m"
|
||||
AQUA="\033[36m"
|
||||
|
||||
END="\033[0m"
|
||||
|
||||
UNDERLINE="\033[4m"
|
||||
BOLD="\033[1m"
|
||||
ITALIC="\033[3m"
|
||||
TITLE=${BLUE}${BOLD}${UNDERLINE}
|
||||
STEPTITLE=${BLUERIGHTARROW}" "${BOLD}${ITALIC}
|
||||
SUBSTEPTITLE=${MINIARROW}${MINIARROW}${MINIARROW}" "${ITALIC}
|
||||
RIGHTARROW="\xE2\x96\xB6"
|
||||
MINIARROW="\xE2\x96\xBB"
|
||||
BLUERIGHTARROW=${BLUE}${RIGHTARROW}${END}
|
||||
GREENRIGHTARROW=${GREEN}${RIGHTARROW}${END}
|
||||
|
||||
ERROR=${RED}
|
||||
|
||||
TICK="\xE2\x9C\x94"
|
||||
CROSS="\xE2\x9C\x97"
|
||||
GREENTICK=${GREEN}${TICK}${END}
|
||||
REDCROSS=${RED}${CROSS}${END}
|
||||
|
||||
|
||||
SPACER="\n\n"
|
||||
|
||||
while getopts r:n:i:t:d:h:u:p: flag
|
||||
do
|
||||
case "${flag}" in
|
||||
r) REGISTRY=${OPTARG};;
|
||||
n) NAMESPACE=${OPTARG};;
|
||||
i) IMAGE=${OPTARG};;
|
||||
t) TAG=${OPTARG};;
|
||||
d) DIGESTS=${OPTARG};;
|
||||
u) USER=${OPTARG};;
|
||||
p) CREDENTIAL=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z $REGISTRY || -z $NAMESPACE || -z $IMAGE || -z $TAG || -z $DIGESTS ]] ; then
|
||||
printf "${REDCROSS} ${ERROR}Missing parameter!${END}\n"
|
||||
printf "${ERROR}$usage${END}\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docker CLI manifest commands require experimental features to be turned on
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
|
||||
MANIFESTS=""
|
||||
for digest in $DIGESTS ; do \
|
||||
MANIFESTS+=" $REGISTRY/$NAMESPACE/$IMAGE@$digest"
|
||||
done
|
||||
|
||||
docker login $REGISTRY -u $USER -p $CREDENTIAL
|
||||
docker manifest create $REGISTRY/$NAMESPACE/$IMAGE:$TAG $MANIFESTS > /dev/null
|
||||
MANIFEST_DIGEST=$(docker manifest push --purge $REGISTRY/$NAMESPACE/$IMAGE:$TAG)
|
||||
|
||||
echo $MANIFEST_DIGEST
|
||||
48
travis-build-scripts/install-credential-helper.sh
Executable file
48
travis-build-scripts/install-credential-helper.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © Copyright IBM Corporation 2020
|
||||
#
|
||||
#
|
||||
# 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.
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7EA0A9C3F273FCD8
|
||||
sudo add-apt-repository "deb [arch=$ARCH] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
sudo apt update
|
||||
sudo apt -y install docker-ce pass
|
||||
|
||||
mkdir -p $GOPATH/src/github.com/docker
|
||||
cd $GOPATH/src/github.com/docker
|
||||
git clone https://github.com/docker/docker-credential-helpers
|
||||
cd docker-credential-helpers
|
||||
make pass
|
||||
cp bin/docker-credential-pass $GOPATH/bin/docker-credential-pass
|
||||
mkdir -p /home/travis/.docker
|
||||
echo '{ "credsStore": "pass" }' | tee /home/travis/.docker/config.json
|
||||
gpg --batch --gen-key <<-EOF
|
||||
%echo generating a standard key
|
||||
Key-Type: DSA
|
||||
Key-Length: 1024
|
||||
Subkey-Type: ELG-E
|
||||
Subkey-Length: 1024
|
||||
Name-Real: Travis CI
|
||||
Name-Email: travis@osism.io
|
||||
Expire-Date: 0
|
||||
%commit
|
||||
%echo done
|
||||
EOF
|
||||
key=$(gpg --no-auto-check-trustdb --list-secret-keys | grep ^sec | cut -d/ -f2 | cut -d" " -f1)
|
||||
gpg --export-secret-keys | gpg2 --import -
|
||||
pass init $key
|
||||
pass insert docker-credential-helpers/docker-pass-initialized-check <<-EOF
|
||||
pass is initialized
|
||||
pass is initialized
|
||||
EOF
|
||||
56
travis-build-scripts/push.sh
Executable file
56
travis-build-scripts/push.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
# © Copyright IBM Corporation 2019, 2020
|
||||
#
|
||||
# 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 {
|
||||
if [[ "$ARCH" = "amd64" || "$ARCH" = "s390x" ]] ; then
|
||||
echo 'Pushing Production image...' && echo -en 'travis_fold:start:push-advancedserver\\r'
|
||||
make push-advancedserver
|
||||
echo -en 'travis_fold:end:push-advancedserver\\r'
|
||||
fi
|
||||
}
|
||||
|
||||
# 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
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
# -*- mode: sh -*-
|
||||
# © Copyright IBM Corporation 2018, 2019
|
||||
#
|
||||
|
||||
# © Copyright IBM Corporation 2019, 2020
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -15,16 +14,22 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Copy in licenses from installed packages
|
||||
|
||||
set -e
|
||||
|
||||
rm -f /licenses/installed_package_notices
|
||||
if [ "$(uname -m)" = "x86_64" ] ; then export ARCH="amd64" ; else export ARCH=$(uname -m) ; fi
|
||||
|
||||
for p in $(rpm -qa | sort)
|
||||
do
|
||||
rpm -qi $p >> /licenses/installed_package_notices
|
||||
printf "\n" >> /licenses/installed_package_notices
|
||||
done
|
||||
echo 'Downgrading Docker (if necessary)...' && echo -en 'travis_fold:start:docker-downgrade\\r'
|
||||
eval "$DOCKER_DOWNGRADE"
|
||||
echo -en 'travis_fold:end:docker-downgrade\\r'
|
||||
|
||||
chmod 0444 /licenses/installed_package_notices
|
||||
## 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
|
||||
38
travis-build-scripts/test.sh
Executable file
38
travis-build-scripts/test.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# © Copyright IBM Corporation 2019, 2020
|
||||
#
|
||||
# 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
|
||||
|
||||
# Use verbose test output
|
||||
export TEST_OPTS_DOCKER="-v"
|
||||
|
||||
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
|
||||
if [[ "$ARCH" = "amd64" || "$ARCH" = "s390x" ]] ; 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
|
||||
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'
|
||||
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
Normal file
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Treat all files in this repo as binary, with no git magic updating
|
||||
# line endings. Windows users contributing to Go will need to use a
|
||||
# modern version of git and editors capable of LF line endings.
|
||||
#
|
||||
# We'll prevent accidental CRLF line endings from entering the repo
|
||||
# via the git-review gofmt checks.
|
||||
#
|
||||
# See golang.org/issue/9281
|
||||
|
||||
* -text
|
||||
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Add no patterns to .hgignore except for files generated by the build.
|
||||
last-change
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user