Compare commits
153 Commits
9.1.4
...
stale-work
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a0a996fe4 | ||
|
|
7fbb8ff076 | ||
|
|
cc956b29f4 | ||
|
|
786e26bccc | ||
|
|
b074eed754 | ||
|
|
f5fdd1008f | ||
|
|
0857c654d2 | ||
|
|
480c3ee027 | ||
|
|
54076af43d | ||
|
|
608f255ab0 | ||
|
|
a927b6e01e | ||
|
|
987a7657ce | ||
|
|
94a78b3122 | ||
|
|
fcc458bf31 | ||
|
|
4580cecf49 | ||
|
|
684106452b | ||
|
|
14987c1170 | ||
|
|
46b0ceede3 | ||
|
|
4bbb447e74 | ||
|
|
ebbbbb04ab | ||
|
|
54bad805c1 | ||
|
|
cecade9845 | ||
|
|
f61a08fe50 | ||
|
|
573fbb8fb1 | ||
|
|
e99c07192d | ||
|
|
9252465cab | ||
|
|
a778eb1cc9 | ||
|
|
2bf2052248 | ||
|
|
d903336fe0 | ||
|
|
b7dcff0bbc | ||
|
|
3e6ceb4bb9 | ||
|
|
b2767947a0 | ||
|
|
a24258834e | ||
|
|
76070234d4 | ||
|
|
d2ea17ec30 | ||
|
|
c0e05be791 | ||
|
|
12a2dee175 | ||
|
|
ac3dcdd0d0 | ||
|
|
4257f6a199 | ||
|
|
5fd9fc5e26 | ||
|
|
adbc95c5d5 | ||
|
|
99a1e4aa74 | ||
|
|
2ae82d71d6 | ||
|
|
8a2faf2955 | ||
|
|
1d41f4b138 | ||
|
|
e1c96655b1 | ||
|
|
68fe4a1dc1 | ||
|
|
adf15b7bd3 | ||
|
|
e77ac9617d | ||
|
|
54824879c5 | ||
|
|
bf8580248b | ||
|
|
e1978541db | ||
|
|
aa7580aa5a | ||
|
|
4366cd8c81 | ||
|
|
2a5242a4d9 | ||
|
|
a4dc545a4f | ||
|
|
f16ce5e4a4 | ||
|
|
03cdf67439 | ||
|
|
e8e86dcc92 | ||
|
|
abf969a64d | ||
|
|
34a55135fb | ||
|
|
dd1d534045 | ||
|
|
c39a532da9 | ||
|
|
efb35ff1b0 | ||
|
|
c2b8753c76 | ||
|
|
f8ae8b0be1 | ||
|
|
e8d26aa79e | ||
|
|
a3e3b0d8c6 | ||
|
|
23f31b1639 | ||
|
|
8d164340c6 | ||
|
|
94ad66661e | ||
|
|
f39f90728f | ||
|
|
a7125b7700 | ||
|
|
9f50b0efaa | ||
|
|
0d5ed76979 | ||
|
|
c37f8f1c4c | ||
|
|
f74777e498 | ||
|
|
55c094a58a | ||
|
|
3d6199e0d8 | ||
|
|
8111761c4f | ||
|
|
4fcdb50928 | ||
|
|
23eba2524e | ||
|
|
678a62f152 | ||
|
|
a2940a4ba8 | ||
|
|
70def702b8 | ||
|
|
f72dc51475 | ||
|
|
afe8aba912 | ||
|
|
444cadf864 | ||
|
|
c2d46d1dff | ||
|
|
6808af107b | ||
|
|
720ecae5bb | ||
|
|
490055e74c | ||
|
|
461529dd98 | ||
|
|
8d7085c18f | ||
|
|
b84581c7ee | ||
|
|
b9dd2f5e79 | ||
|
|
12bcf8b2da | ||
|
|
64a66f6590 | ||
|
|
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 |
22
.github/workflows/stale.yaml
vendored
Normal file
22
.github/workflows/stale.yaml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Close inactive issues and PRs
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "30 1 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
days-before-stale: 90
|
||||||
|
days-before-close: 30
|
||||||
|
stale-issue-label: "stale"
|
||||||
|
stale-pr-label: "stale"
|
||||||
|
stale-issue-message: "This issue is stale because it has been open for 90 days with no activity."
|
||||||
|
close-issue-message: "This issue was closed because it has been inactive for 30 days since being marked as stale."
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
exempt-issue-labels: "bug,enhancement,documentation"
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,3 +12,5 @@ vendor/github.com/prometheus/client_model/.classpath
|
|||||||
vendor/github.com/prometheus/client_model/.project
|
vendor/github.com/prometheus/client_model/.project
|
||||||
vendor/github.com/prometheus/client_model/.settings*
|
vendor/github.com/prometheus/client_model/.settings*
|
||||||
gosec_results.json
|
gosec_results.json
|
||||||
|
internal/qmgrauth/qmgroam/patch
|
||||||
|
.tagcache
|
||||||
|
|||||||
134
.travis.yml
134
.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");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,72 +12,132 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
dist: xenial
|
dist: bionic
|
||||||
|
group: beta
|
||||||
sudo: required
|
sudo: required
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.12"
|
- "1.13.15"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
go_import_path: "github.com/ibm-messaging/mq-container"
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- downloads
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- RELEASE=""
|
- MAIN_BRANCH=v9.2.3
|
||||||
|
- MQ_LTS_VERSION=9.2.0.1
|
||||||
|
- TAGCACHE_FILE=tagcache
|
||||||
|
- RELEASE=r1
|
||||||
|
- RELEASE_LTS=r1
|
||||||
|
|
||||||
|
go_import_path: "github.com/ibm-messaging/mq-container"
|
||||||
|
|
||||||
|
# cache:
|
||||||
|
# directories:
|
||||||
|
# - downloads
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: build
|
- stage: basic-build
|
||||||
name: "Basic build"
|
if: branch != v9.2.3 AND tag IS blank
|
||||||
if: branch != private-master AND tag IS blank
|
name: "Basic AMD64 build"
|
||||||
os: linux
|
os: linux
|
||||||
env:
|
env:
|
||||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_AMD64
|
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_AMD64
|
||||||
script: bash -e travis-build-scripts/run.sh
|
script: bash -e travis-build-scripts/run.sh
|
||||||
- if: branch = private-master OR tag =~ ^pre-release*
|
|
||||||
|
# CD Build
|
||||||
|
|
||||||
|
- stage: global-tag
|
||||||
|
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
|
||||||
|
name: "Generate Global Tag"
|
||||||
|
os: linux
|
||||||
|
script: bash -e travis-build-scripts/global-tag.sh
|
||||||
|
- stage: build
|
||||||
|
if: branch = v9.2.3 OR tag =~ ^release-candidate*
|
||||||
name: "Multi-Arch AMD64 build"
|
name: "Multi-Arch AMD64 build"
|
||||||
os: linux
|
os: linux
|
||||||
env:
|
env:
|
||||||
- BUILD_ALL=true
|
- BUILD_ALL=true
|
||||||
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_AMD64
|
- MQ_ARCHIVE_REPOSITORY=$MQ_923_ARCHIVE_REPOSITORY_AMD64
|
||||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_AMD64
|
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_AMD64
|
||||||
script: bash -e travis-build-scripts/run.sh
|
script: bash -e travis-build-scripts/run.sh
|
||||||
- if: branch = private-master OR tag =~ ^pre-release*
|
# - if: branch = v9.2.3 OR tag =~ ^release-candidate*
|
||||||
name: "Multi-Arch PPC64LE build"
|
# name: "Multi-Arch PPC64LE build"
|
||||||
os: linux-ppc64le
|
# os: linux-ppc64le
|
||||||
env:
|
# env:
|
||||||
- BUILD_ALL=true
|
# - BUILD_ALL=true
|
||||||
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
# - TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
||||||
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_PPC64LE
|
# # - MQ_ARCHIVE_REPOSITORY=$MQ_923_ARCHIVE_REPOSITORY_PPC64LE
|
||||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_PPC64LE
|
# - MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_PPC64LE
|
||||||
script: bash -e travis-build-scripts/run.sh
|
# script: bash -e travis-build-scripts/run.sh
|
||||||
- if: branch = private-master OR tag =~ ^pre-release*
|
- stage: build
|
||||||
|
if: branch = v9.2.3 OR tag =~ ^release-candidate*
|
||||||
name: "Multi-Arch S390X build"
|
name: "Multi-Arch S390X build"
|
||||||
os: linux-s390
|
os: linux-s390
|
||||||
env:
|
env:
|
||||||
- BUILD_ALL=true
|
- BUILD_ALL=true
|
||||||
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
||||||
- MQ_ARCHIVE_REPOSITORY=$MQ_914_ARCHIVE_REPOSITORY_S390X
|
- MQ_ARCHIVE_REPOSITORY=$MQ_923_ARCHIVE_REPOSITORY_S390X
|
||||||
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_914_ARCHIVE_REPOSITORY_DEV_S390X
|
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_S390X
|
||||||
|
script: bash -e travis-build-scripts/run.sh
|
||||||
|
- stage: push-manifest
|
||||||
|
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
|
||||||
|
name: "Push Manifest-list to registry"
|
||||||
|
env:
|
||||||
|
- PUSH_MANIFEST_ONLY=true
|
||||||
|
script: bash -e travis-build-scripts/run.sh
|
||||||
|
|
||||||
|
# LTS Build
|
||||||
|
|
||||||
|
- stage: global-tag
|
||||||
|
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
|
||||||
|
name: "Generate Global Tag"
|
||||||
|
os: linux
|
||||||
|
env:
|
||||||
|
- LTS=true
|
||||||
|
- TAGCACHE_FILE=tagcache-lts
|
||||||
|
- MQ_VERSION=$MQ_LTS_VERSION
|
||||||
|
- RELEASE=$RELEASE_LTS
|
||||||
|
script: bash -e travis-build-scripts/global-tag.sh
|
||||||
|
- stage: build
|
||||||
|
if: branch = v9.2.3 OR tag =~ ^release-candidate*
|
||||||
|
name: "Multi-Arch AMD64 build"
|
||||||
|
os: linux
|
||||||
|
env:
|
||||||
|
- LTS=true
|
||||||
|
- TAGCACHE_FILE=tagcache-lts
|
||||||
|
- MQ_VERSION=$MQ_LTS_VERSION
|
||||||
|
- MQ_ARCHIVE_REPOSITORY=$MQ_9201_EUS_ARCHIVE_REPOSITORY_AMD64
|
||||||
|
- RELEASE=$RELEASE_LTS
|
||||||
|
script: bash -e travis-build-scripts/run.sh
|
||||||
|
- stage: build
|
||||||
|
if: branch = v9.2.3 OR tag =~ ^release-candidate*
|
||||||
|
name: "Multi-Arch S390X build"
|
||||||
|
os: linux-s390
|
||||||
|
env:
|
||||||
|
- LTS=true
|
||||||
|
- TAGCACHE_FILE=tagcache-lts
|
||||||
|
- MQ_VERSION=$MQ_LTS_VERSION
|
||||||
|
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
|
||||||
|
- MQ_ARCHIVE_REPOSITORY=$MQ_9201_EUS_ARCHIVE_REPOSITORY_S390X
|
||||||
|
- RELEASE=$RELEASE_LTS
|
||||||
|
script: bash -e travis-build-scripts/run.sh
|
||||||
|
- stage: push-manifest
|
||||||
|
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
|
||||||
|
name: "Push Manifest-list to registry"
|
||||||
|
env:
|
||||||
|
- LTS=true
|
||||||
|
- TAGCACHE_FILE=tagcache-lts
|
||||||
|
- MQ_VERSION=$MQ_LTS_VERSION
|
||||||
|
- PUSH_MANIFEST_ONLY=true
|
||||||
|
- RELEASE=$RELEASE_LTS
|
||||||
script: bash -e travis-build-scripts/run.sh
|
script: bash -e travis-build-scripts/run.sh
|
||||||
- stage: deploy
|
|
||||||
name: "Pre-release deploy"
|
|
||||||
if: tag =~ ^pre-release*
|
|
||||||
script: bash -e travis-build-scripts/release.sh staging
|
|
||||||
- name: "Production release deploy"
|
|
||||||
if: tag =~ ^production-release*
|
|
||||||
script: bash -e travis-build-scripts/release.sh production
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- make install-build-deps
|
- make install-build-deps
|
||||||
|
- make install-credential-helper
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- echo nothing
|
- echo nothing
|
||||||
|
|||||||
31
CHANGELOG.md
31
CHANGELOG.md
@@ -1,11 +1,38 @@
|
|||||||
# Change log
|
# Change log
|
||||||
|
|
||||||
|
## 9.2.3.0 (2021-07-22)
|
||||||
|
|
||||||
|
* Updated to MQ version 9.2.3.0
|
||||||
|
|
||||||
|
## 9.2.2.0 (2021-03-26)
|
||||||
|
|
||||||
|
* Updated to MQ version 9.2.2.0
|
||||||
|
|
||||||
|
## 9.2.1.0 (2020-02-18)
|
||||||
|
|
||||||
|
* Updated to MQ version 9.2.1.0
|
||||||
|
|
||||||
|
|
||||||
|
## 9.2.0.1-LTS (2020-12-04)
|
||||||
|
|
||||||
|
* Added support for MQ Long Term Support (production licensed only) in the mq-container
|
||||||
|
|
||||||
|
## 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)
|
## 9.1.4.0 (2019-12-06)
|
||||||
|
|
||||||
* Updated to MQ version 9.1.4.0
|
* Updated to MQ version 9.1.4.0
|
||||||
* Updated to use UBI8 as base image
|
* Updated to use UBI8 as base image
|
||||||
* Added required security settings to self signed certificates to align with macOS Catalina requirements
|
* Added required security settings to self signed certificates to align with macOS Catalina requirements
|
||||||
|
|
||||||
## 9.1.3.0 (2019-07-19)
|
## 9.1.3.0 (2019-07-19)
|
||||||
|
|
||||||
* Updated to MQ version 9.1.3.0
|
* Updated to MQ version 9.1.3.0
|
||||||
@@ -26,7 +53,7 @@
|
|||||||
* Security fixes
|
* Security fixes
|
||||||
* Web console added to production image
|
* Web console added to production image
|
||||||
* Container built on RedHat host
|
* Container built on RedHat host
|
||||||
|
|
||||||
## 9.1.2.0 (2019-03-21)
|
## 9.1.2.0 (2019-03-21)
|
||||||
|
|
||||||
* Updated to MQ version 9.1.2.0
|
* Updated to MQ version 9.1.2.0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# © Copyright IBM Corporation 2015, 2019
|
# © Copyright IBM Corporation 2015, 2021
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -13,40 +13,45 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
ARG BASE_IMAGE=registry.redhat.io/ubi8/ubi-minimal
|
ARG BASE_IMAGE=registry.redhat.io/ubi8/ubi-minimal
|
||||||
ARG BASE_TAG=8.1-279
|
ARG BASE_TAG=8.4-205
|
||||||
|
ARG GO_WORKDIR=/opt/app-root/src/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.3.0-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Build stage to build Go code
|
# Build stage to build Go code
|
||||||
###############################################################################
|
###############################################################################
|
||||||
FROM registry.redhat.io/rhel8/go-toolset:1.12.8-11 as builder
|
FROM registry.redhat.io/ubi8/go-toolset:1.15.13-4 as builder
|
||||||
# FROM docker.io/centos/go-toolset-7-centos7 as builder
|
|
||||||
# The URL to download the MQ installer from in tar.gz format
|
# The URL to download the MQ installer from in tar.gz format
|
||||||
# This assumes an archive containing the MQ RPM install packages
|
# This assumes an archive containing the MQ Non-Install packages
|
||||||
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev912_linux_x86-64.tar.gz"
|
ARG MQ_URL
|
||||||
ARG IMAGE_REVISION="Not specified"
|
ARG IMAGE_REVISION="Not specified"
|
||||||
ARG IMAGE_SOURCE="Not specified"
|
ARG IMAGE_SOURCE="Not specified"
|
||||||
ARG IMAGE_TAG="Not specified"
|
ARG IMAGE_TAG="Not specified"
|
||||||
ARG MQM_UID=888
|
ARG GO_WORKDIR
|
||||||
USER 0
|
USER 0
|
||||||
COPY install-mq.sh /usr/local/bin/
|
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 \
|
&& sleep 1 \
|
||||||
&& MQ_PACKAGES="MQSeriesRuntime-*.rpm MQSeriesSDK-*.rpm MQSeriesSamples*.rpm" install-mq.sh $MQM_UID
|
&& INSTALL_SDK=1 install-mq.sh \
|
||||||
WORKDIR /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/
|
&& chown -R 1001:root /opt/mqm/*
|
||||||
|
WORKDIR $GO_WORKDIR/
|
||||||
COPY cmd/ ./cmd
|
COPY cmd/ ./cmd
|
||||||
COPY internal/ ./internal
|
COPY internal/ ./internal
|
||||||
COPY pkg/ ./pkg
|
COPY pkg/ ./pkg
|
||||||
COPY vendor/ ./vendor
|
COPY vendor/ ./vendor
|
||||||
ENV PATH="${PATH}:/opt/rh/go-toolset-1.11/root/usr/bin" \
|
ENV CGO_CFLAGS="-I/opt/mqm/inc/" \
|
||||||
CGO_CFLAGS="-I/opt/mqm/inc/" \
|
|
||||||
CGO_LDFLAGS_ALLOW="-Wl,-rpath.*"
|
CGO_LDFLAGS_ALLOW="-Wl,-rpath.*"
|
||||||
|
ENV PATH="${PATH}:/opt/mqm/bin"
|
||||||
RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/
|
RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/
|
||||||
RUN go build ./cmd/chkmqready/
|
RUN go build ./cmd/chkmqready/
|
||||||
RUN go build ./cmd/chkmqhealthy/
|
RUN go build ./cmd/chkmqhealthy/
|
||||||
|
RUN go build ./cmd/chkmqstarted/
|
||||||
RUN go build ./cmd/runmqdevserver/
|
RUN go build ./cmd/runmqdevserver/
|
||||||
RUN go test -v ./cmd/runmqdevserver/...
|
RUN go test -v ./cmd/runmqdevserver/...
|
||||||
RUN go test -v ./cmd/runmqserver/
|
RUN go test -v ./cmd/runmqserver/
|
||||||
RUN go test -v ./cmd/chkmqready/
|
RUN go test -v ./cmd/chkmqready/
|
||||||
RUN go test -v ./cmd/chkmqhealthy/
|
RUN go test -v ./cmd/chkmqhealthy/
|
||||||
|
RUN go test -v ./cmd/chkmqstarted/
|
||||||
RUN go test -v ./pkg/...
|
RUN go test -v ./pkg/...
|
||||||
RUN go test -v ./internal/...
|
RUN go test -v ./internal/...
|
||||||
RUN go vet ./cmd/... ./internal/...
|
RUN go vet ./cmd/... ./internal/...
|
||||||
@@ -56,15 +61,14 @@ RUN go vet ./cmd/... ./internal/...
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
FROM $BASE_IMAGE:$BASE_TAG AS mq-server
|
FROM $BASE_IMAGE:$BASE_TAG AS mq-server
|
||||||
# The MQ packages to install - see install-mq.sh for default value
|
# The MQ packages to install - see install-mq.sh for default value
|
||||||
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev914_linux_x86-64.tar.gz"
|
ARG MQ_URL
|
||||||
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 BASE_IMAGE
|
ARG BASE_IMAGE
|
||||||
ARG BASE_TAG
|
ARG BASE_TAG
|
||||||
|
ARG GO_WORKDIR
|
||||||
LABEL summary="IBM MQ Advanced Server"
|
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 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 vendor="IBM"
|
||||||
|
LABEL maintainer="IBM"
|
||||||
LABEL distribution-scope="private"
|
LABEL distribution-scope="private"
|
||||||
LABEL authoritative-source-url="https://www.ibm.com/software/passportadvantage/"
|
LABEL authoritative-source-url="https://www.ibm.com/software/passportadvantage/"
|
||||||
LABEL url="https://www.ibm.com/products/mq/advanced"
|
LABEL url="https://www.ibm.com/products/mq/advanced"
|
||||||
@@ -76,44 +80,73 @@ LABEL base-image-release=$BASE_TAG
|
|||||||
COPY install-mq.sh /usr/local/bin/
|
COPY install-mq.sh /usr/local/bin/
|
||||||
COPY install-mq-server-prereqs.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.
|
# 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 \
|
&& sleep 1 \
|
||||||
&& install-mq-server-prereqs.sh $MQM_UID \
|
&& install-mq-server-prereqs.sh \
|
||||||
&& install-mq.sh $MQM_UID
|
&& install-mq.sh \
|
||||||
|
&& /opt/mqm/bin/security/amqpamcf \
|
||||||
|
&& chown -R 1001:root /opt/mqm/*
|
||||||
# Create a directory for runtime data from runmqserver
|
# Create a directory for runtime data from runmqserver
|
||||||
RUN mkdir -p /run/runmqserver \
|
RUN mkdir -p /run/runmqserver \
|
||||||
&& chown mqm:mqm /run/runmqserver
|
&& chown 1001:root /run/runmqserver
|
||||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/runmqserver /usr/local/bin/
|
COPY --from=builder $GO_WORKDIR/runmqserver /usr/local/bin/
|
||||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/chkmq* /usr/local/bin/
|
COPY --from=builder $GO_WORKDIR/chkmq* /usr/local/bin/
|
||||||
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
|
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
|
||||||
|
COPY ha/native-ha.ini.tpl /etc/mqm/native-ha.ini.tpl
|
||||||
# Copy web XML files
|
# Copy web XML files
|
||||||
COPY web /etc/mqm/web
|
COPY web /etc/mqm/web
|
||||||
COPY etc/mqm/*.tpl /etc/mqm/
|
COPY etc/mqm/*.tpl /etc/mqm/
|
||||||
RUN chmod ug+x /usr/local/bin/runmqserver \
|
RUN chmod ug+x /usr/local/bin/runmqserver \
|
||||||
&& chown mqm:mqm /usr/local/bin/*mq* \
|
&& chown 1001:root /usr/local/bin/*mq* \
|
||||||
&& chmod ug+xs /usr/local/bin/chkmq* \
|
&& chmod ug+x /usr/local/bin/chkmq* \
|
||||||
&& chown -R mqm:mqm /etc/mqm/* \
|
&& chown -R 1001:root /etc/mqm/* \
|
||||||
&& install --directory --mode 0775 --owner mqm --group root /run/runmqserver \
|
&& install --directory --mode 2775 --owner 1001 --group root /run/runmqserver \
|
||||||
&& touch /run/termination-log \
|
&& touch /run/termination-log \
|
||||||
&& chown mqm:root /run/termination-log \
|
&& chown 1001:root /run/termination-log \
|
||||||
&& chmod 0660 /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
|
# Always use port 1414 for MQ & 9157 for the metrics
|
||||||
EXPOSE 1414 9157 9443
|
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
|
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"]
|
ENTRYPOINT ["runmqserver"]
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Build stage to build C code for custom authorization service (developer-only)
|
||||||
|
###############################################################################
|
||||||
|
FROM registry.redhat.io/rhel8/gcc-toolset-9-toolchain as cbuilder
|
||||||
|
# The URL to download the MQ installer from in tar.gz format
|
||||||
|
# This assumes an archive containing the MQ Non-Install packages
|
||||||
|
ARG MQ_URL
|
||||||
|
USER 0
|
||||||
|
# Install the Apache Portable Runtime code (used for htpasswd hash checking)
|
||||||
|
RUN yum -y install apr-devel apr-util-openssl apr-util-devel
|
||||||
|
# Install MQ client
|
||||||
|
COPY install-mq.sh /usr/local/bin/
|
||||||
|
RUN mkdir /opt/mqm \
|
||||||
|
&& chmod a+x /usr/local/bin/install-mq.sh \
|
||||||
|
&& sleep 1 \
|
||||||
|
&& INSTALL_SDK=1 install-mq.sh \
|
||||||
|
&& chown -R 1001:root /opt/mqm/*
|
||||||
|
COPY authservice/ /opt/app-root/src/authservice/
|
||||||
|
WORKDIR /opt/app-root/src/authservice/mqhtpass
|
||||||
|
RUN make all
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Add default developer config
|
# Add default developer config
|
||||||
###############################################################################
|
###############################################################################
|
||||||
FROM mq-server AS mq-dev-server
|
FROM mq-server AS mq-dev-server
|
||||||
ARG MQM_UID=888
|
|
||||||
ARG BASE_IMAGE
|
ARG BASE_IMAGE
|
||||||
ARG BASE_TAG
|
ARG BASE_TAG
|
||||||
|
ARG GO_WORKDIR
|
||||||
# Enable MQ developer default configuration
|
# Enable MQ developer default configuration
|
||||||
ENV MQ_DEV=true
|
ENV MQ_DEV=true
|
||||||
# Default administrator password
|
|
||||||
ENV MQ_ADMIN_PASSWORD=passw0rd
|
|
||||||
LABEL summary="IBM MQ Advanced for Developers Server"
|
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 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 vendor="IBM"
|
||||||
@@ -126,29 +159,29 @@ LABEL io.k8s.description="Simplify, accelerate and facilitate the reliable excha
|
|||||||
LABEL base-image=$BASE_IMAGE
|
LABEL base-image=$BASE_IMAGE
|
||||||
LABEL base-image-release=$BASE_TAG
|
LABEL base-image-release=$BASE_TAG
|
||||||
USER 0
|
USER 0
|
||||||
|
COPY --from=cbuilder /opt/app-root/src/authservice/mqhtpass/build/mqhtpass.so /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/
|
COPY incubating/mqadvanced-server-dev/install-extra-packages.sh /usr/local/bin/
|
||||||
RUN chmod u+x /usr/local/bin/install-extra-packages.sh \
|
RUN chmod u+x /usr/local/bin/install-extra-packages.sh \
|
||||||
&& sleep 1 \
|
&& sleep 1 \
|
||||||
&& install-extra-packages.sh
|
&& 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
|
# Create a directory for runtime data from runmqserver
|
||||||
RUN mkdir -p /run/runmqdevserver \
|
RUN mkdir -p /run/runmqdevserver \
|
||||||
&& chown mqm:mqm /run/runmqdevserver
|
&& chown 1001:root /run/runmqdevserver
|
||||||
COPY --from=builder /opt/app-root/src/go/src/github.com/ibm-messaging/mq-container/runmqdevserver /usr/local/bin/
|
COPY --from=builder $GO_WORKDIR/runmqdevserver /usr/local/bin/
|
||||||
# Copy template files
|
# Copy template files
|
||||||
COPY incubating/mqadvanced-server-dev/*.tpl /etc/mqm/
|
COPY incubating/mqadvanced-server-dev/*.tpl /etc/mqm/
|
||||||
# Copy web XML files for default developer configuration
|
# Copy web XML files for default developer configuration
|
||||||
COPY incubating/mqadvanced-server-dev/web /etc/mqm/web
|
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* \
|
&& chmod +x /usr/local/bin/runmq* \
|
||||||
&& install --directory --mode 0775 --owner mqm --group root /run/runmqdevserver
|
&& install --directory --mode 2775 --owner 1001 --group root /run/runmqdevserver
|
||||||
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1 MQ_GENERATE_CERTIFICATE_HOSTNAME=localhost
|
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1 MQ_GENERATE_CERTIFICATE_HOSTNAME=localhost
|
||||||
USER $MQM_UID
|
ENV LD_LIBRARY_PATH=/opt/mqm/lib64
|
||||||
|
ENV MQ_CONNAUTH_USE_HTP=true
|
||||||
|
ENV MQS_PERMIT_UNKNOWN_ID=true
|
||||||
|
USER 1001
|
||||||
ENTRYPOINT ["runmqdevserver"]
|
ENTRYPOINT ["runmqdevserver"]
|
||||||
|
|||||||
218
Makefile
218
Makefile
@@ -1,4 +1,4 @@
|
|||||||
# © Copyright IBM Corporation 2017, 2019
|
# © Copyright IBM Corporation 2017, 2021
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -16,67 +16,71 @@
|
|||||||
# Conditional variables - you can override the values of these variables from
|
# Conditional variables - you can override the values of these variables from
|
||||||
# the command line
|
# the command line
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
include config.env
|
||||||
|
|
||||||
# RELEASE shows what release of the container code has been built
|
# RELEASE shows what release of the container code has been built
|
||||||
RELEASE ?=
|
RELEASE ?=
|
||||||
# MQ_VERSION is the fully qualified MQ version number to build
|
|
||||||
MQ_VERSION ?= 9.1.4.0
|
|
||||||
# MQ_ARCHIVE_REPOSITORY is a remote repository from which to pull the MQ_ARCHIVE (if required)
|
# MQ_ARCHIVE_REPOSITORY is a remote repository from which to pull the MQ_ARCHIVE (if required)
|
||||||
MQ_ARCHIVE_REPOSITORY ?=
|
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 is a remote repository from which to pull the MQ_ARCHIVE_DEV (if required)
|
||||||
MQ_ARCHIVE_REPOSITORY_DEV ?=
|
MQ_ARCHIVE_REPOSITORY_DEV ?=
|
||||||
# MQ_ARCHIVE_REPOSITORY_USER is the user for the remote repository (if required)
|
# MQ_ARCHIVE_REPOSITORY_USER is the user for the remote repository (if required)
|
||||||
MQ_ARCHIVE_REPOSITORY_USER ?=
|
MQ_ARCHIVE_REPOSITORY_USER ?=
|
||||||
# MQ_ARCHIVE_REPOSITORY_CREDENTIAL is the password/API key for the remote repository (if required)
|
# MQ_ARCHIVE_REPOSITORY_CREDENTIAL is the password/API key for the remote repository (if required)
|
||||||
MQ_ARCHIVE_REPOSITORY_CREDENTIAL ?=
|
MQ_ARCHIVE_REPOSITORY_CREDENTIAL ?=
|
||||||
# MQ_ARCHIVE is the name of the file, under the downloads directory, from which MQ Advanced can
|
# MQ_ARCHIVE is the name of the file, under the downloads directory, from which MQ Advanced can
|
||||||
# be installed. The default value is derived from MQ_VERSION, BASE_IMAGE and architecture
|
# be installed. Does not apply to MQ Advanced for Developers
|
||||||
# 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 ?= IBM_MQ_$(MQ_VERSION_VRM)_$(MQ_ARCHIVE_TYPE)_$(MQ_ARCHIVE_ARCH).tar.gz
|
|
||||||
# MQ_ARCHIVE_DEV is the name of the file, under the downloads directory, from which MQ Advanced
|
# MQ_ARCHIVE_DEV is the name of the file, under the downloads directory, from which MQ Advanced
|
||||||
# for Developers can be installed
|
# 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 specifies the archive to use for building the golang programs. Defaults vary on developer or advanced.
|
||||||
MQ_SDK_ARCHIVE ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
|
MQ_SDK_ARCHIVE ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
|
||||||
# Options to `go test` for the Docker tests
|
# Options to `go test` for the Docker tests
|
||||||
TEST_OPTS_DOCKER ?=
|
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 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 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_MANIFEST_TAG is the tag to use for fat-manifest
|
||||||
|
MQ_MANIFEST_TAG ?= $(MQ_VERSION)$(RELEASE_TAG)$(LTS_TAG)$(MQ_MANIFEST_TAG_SUFFIX)
|
||||||
# MQ_TAG is the tag of the built MQ Advanced image & MQ Advanced for Developers image
|
# MQ_TAG is the tag of the built MQ Advanced image & MQ Advanced for Developers image
|
||||||
MQ_TAG ?=$(MQ_VERSION)-$(ARCH)
|
MQ_TAG ?= $(MQ_MANIFEST_TAG)-$(ARCH)
|
||||||
# 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 is the container command to run. "podman" or "docker"
|
||||||
COMMAND ?=$(shell type -p podman 2>&1 >/dev/null && echo podman || echo docker)
|
COMMAND ?=$(shell type -p podman 2>&1 >/dev/null && echo podman || echo docker)
|
||||||
# MQ_DELIVERY_REGISTRY_HOSTNAME is a remote registry to push the MQ Image to (if required)
|
# MQ_DELIVERY_REGISTRY_HOSTNAME is a remote registry to push the MQ Image to (if required)
|
||||||
MQ_DELIVERY_REGISTRY_HOSTNAME ?=
|
MQ_DELIVERY_REGISTRY_HOSTNAME ?=
|
||||||
# MQ_DELIVERY_REGISTRY_NAMESPACE is the namespace/path on the delivery registry (if required)
|
# MQ_DELIVERY_REGISTRY_NAMESPACE is the namespace/path on the delivery registry (if required)
|
||||||
MQ_DELIVERY_REGISTRY_NAMESPACE ?=
|
MQ_DELIVERY_REGISTRY_NAMESPACE ?=
|
||||||
# MQ_DELIVERY_REGISTRY_USER is the user for the remote registry (if required)
|
# MQ_DELIVERY_REGISTRY_USER is the user for the remote registry (if required)
|
||||||
MQ_DELIVERY_REGISTRY_USER ?=
|
MQ_DELIVERY_REGISTRY_USER ?=
|
||||||
# MQ_DELIVERY_REGISTRY_CREDENTIAL is the password/API key for the remote registry (if required)
|
# MQ_DELIVERY_REGISTRY_CREDENTIAL is the password/API key for the remote registry (if required)
|
||||||
MQ_DELIVERY_REGISTRY_CREDENTIAL ?=
|
MQ_DELIVERY_REGISTRY_CREDENTIAL ?=
|
||||||
# REGISTRY_USER is the username used to login to the Red Hat registry
|
# REGISTRY_USER is the username used to login to the Red Hat registry
|
||||||
REGISTRY_USER ?=
|
REGISTRY_USER ?=
|
||||||
# REGISTRY_PASS is the password used to login to the Red Hat registry
|
# REGISTRY_PASS is the password used to login to the Red Hat registry
|
||||||
REGISTRY_PASS ?=
|
REGISTRY_PASS ?=
|
||||||
# ARCH is the platform architecture (e.g. amd64, ppc64le or s390x)
|
# ARCH is the platform architecture (e.g. amd64, ppc64le or s390x)
|
||||||
ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
|
ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
|
||||||
|
# LTS is a boolean value to enable/disable LTS container build
|
||||||
|
LTS ?= false
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Other variables
|
# Other variables
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
# Build doesn't work if BuildKit is enabled
|
||||||
|
DOCKER_BUILDKIT=0
|
||||||
GO_PKG_DIRS = ./cmd ./internal ./test
|
GO_PKG_DIRS = ./cmd ./internal ./test
|
||||||
MQ_ARCHIVE_TYPE=LINUX
|
MQ_ARCHIVE_TYPE=LINUX
|
||||||
MQ_ARCHIVE_DEV_PLATFORM=linux
|
MQ_ARCHIVE_DEV_TYPE=Linux
|
||||||
# BUILD_SERVER_CONTAINER is the name of the web server container used at build time
|
# BUILD_SERVER_CONTAINER is the name of the web server container used at build time
|
||||||
BUILD_SERVER_CONTAINER=build-server
|
BUILD_SERVER_CONTAINER=build-server
|
||||||
# NUM_CPU is the number of CPUs available to Docker. Used to control how many
|
# NUM_CPU is the number of CPUs available to Docker. Used to control how many
|
||||||
# test run in parallel
|
# 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 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=$(lastword $(subst /, ,$(subst :,-,$(BASE_IMAGE))))
|
||||||
#BASE_IMAGE_TAG=$(subst /,-,$(subst :,-,$(BASE_IMAGE)))
|
#BASE_IMAGE_TAG=$(subst /,-,$(subst :,-,$(BASE_IMAGE)))
|
||||||
@@ -88,7 +92,7 @@ IMAGE_REVISION=$(shell git rev-parse HEAD)
|
|||||||
IMAGE_SOURCE=$(shell git config --get remote.origin.url)
|
IMAGE_SOURCE=$(shell git config --get remote.origin.url)
|
||||||
EMPTY:=
|
EMPTY:=
|
||||||
SPACE:= $(EMPTY) $(EMPTY)
|
SPACE:= $(EMPTY) $(EMPTY)
|
||||||
# MQ_VERSION_VRM is MQ_VERSION with only the Version, Release and Modifier fields (no Fix field). e.g. 9.1.4 instead of 9.1.4.0
|
# MQ_VERSION_VRM is MQ_VERSION with only the Version, Release and Modifier fields (no Fix field). e.g. 9.2.0 instead of 9.2.0.0
|
||||||
MQ_VERSION_VRM=$(subst $(SPACE),.,$(wordlist 1,3,$(subst .,$(SPACE),$(MQ_VERSION))))
|
MQ_VERSION_VRM=$(subst $(SPACE),.,$(wordlist 1,3,$(subst .,$(SPACE),$(MQ_VERSION))))
|
||||||
|
|
||||||
ifneq (,$(findstring Microsoft,$(shell uname -r)))
|
ifneq (,$(findstring Microsoft,$(shell uname -r)))
|
||||||
@@ -102,44 +106,77 @@ endif
|
|||||||
# Try to figure out which archive to use from the architecture
|
# Try to figure out which archive to use from the architecture
|
||||||
ifeq "$(ARCH)" "amd64"
|
ifeq "$(ARCH)" "amd64"
|
||||||
MQ_ARCHIVE_ARCH=X86-64
|
MQ_ARCHIVE_ARCH=X86-64
|
||||||
MQ_DEV_ARCH=x86-64
|
MQ_ARCHIVE_DEV_ARCH=X64
|
||||||
else ifeq "$(ARCH)" "ppc64le"
|
else ifeq "$(ARCH)" "ppc64le"
|
||||||
MQ_ARCHIVE_ARCH=LE_POWER
|
MQ_ARCHIVE_ARCH=PPC64LE
|
||||||
MQ_DEV_ARCH=ppcle
|
|
||||||
else ifeq "$(ARCH)" "s390x"
|
else ifeq "$(ARCH)" "s390x"
|
||||||
MQ_ARCHIVE_ARCH=SYSTEM_Z
|
MQ_ARCHIVE_ARCH=S390X
|
||||||
MQ_DEV_ARCH=s390x
|
|
||||||
endif
|
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
|
|
||||||
MQ_ARCHIVE_DEV_9.1.4.0=mqadv_dev914_$(MQ_ARCHIVE_DEV_PLATFORM)_$(MQ_DEV_ARCH).tar.gz
|
|
||||||
|
|
||||||
ifneq "$(RELEASE)" "$(EMPTY)"
|
# LTS_TAG is the tag modifier for an LTS container build
|
||||||
MQ_IMAGE_FULL_RELEASE_NAME=ibm-mqadvanced-server:$(MQ_VERSION)-$(RELEASE)-$(ARCH)
|
LTS_TAG=
|
||||||
MQ_IMAGE_DEV_FULL_RELEASE_NAME=ibm-mqadvanced-server-dev:$(MQ_VERSION)-$(RELEASE)-$(ARCH)
|
ifeq "$(LTS)" "true"
|
||||||
|
ifneq "$(LTS_TAG_OVERRIDE)" "$(EMPTY)"
|
||||||
|
LTS_TAG=$(LTS_TAG_OVERRIDE)
|
||||||
else
|
else
|
||||||
MQ_IMAGE_FULL_RELEASE_NAME=ibm-mqadvanced-server:$(MQ_VERSION)-$(ARCH)
|
LTS_TAG=-lts
|
||||||
MQ_IMAGE_DEV_FULL_RELEASE_NAME=ibm-mqadvanced-server-dev:$(MQ_VERSION)-$(ARCH)
|
endif
|
||||||
|
MQ_ARCHIVE:=$(MQ_VERSION)-IBM-MQ-Advanced-Non-Install-Linux$(MQ_ARCHIVE_ARCH).tar.gz
|
||||||
|
MQ_DELIVERY_REGISTRY_NAMESPACE:=$(MQ_DELIVERY_REGISTRY_NAMESPACE)$(LTS_TAG)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(findstring release-candidate,$(TRAVIS_TAG)))
|
||||||
|
MQ_DELIVERY_REGISTRY_NAMESPACE=release-candidates
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq "$(MQ_DELIVERY_REGISTRY_NAMESPACE)" "$(EMPTY)"
|
ifneq "$(MQ_DELIVERY_REGISTRY_NAMESPACE)" "$(EMPTY)"
|
||||||
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)/$(MQ_DELIVERY_REGISTRY_NAMESPACE)
|
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)/$(MQ_DELIVERY_REGISTRY_NAMESPACE)
|
||||||
else
|
else
|
||||||
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)
|
MQ_DELIVERY_REGISTRY_FULL_PATH=$(MQ_DELIVERY_REGISTRY_HOSTNAME)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# image tagging
|
||||||
|
|
||||||
ifneq "$(RELEASE)" "$(EMPTY)"
|
ifneq "$(RELEASE)" "$(EMPTY)"
|
||||||
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server
|
|
||||||
MQ_IMAGE_DEVSERVER=ibm-mqadvanced-server-dev
|
|
||||||
MQ_TAG=$(MQ_VERSION)-$(RELEASE)-$(ARCH)
|
|
||||||
EXTRA_LABELS=--label release=$(RELEASE)
|
EXTRA_LABELS=--label release=$(RELEASE)
|
||||||
|
RELEASE_TAG="-$(RELEASE)"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq "$(TIMESTAMPFLAT)" "$(EMPTY)"
|
||||||
|
TIMESTAMPFLAT=$(shell date "+%Y%m%d%H%M%S")
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq "$(GIT_COMMIT)" "$(EMPTY)"
|
||||||
|
GIT_COMMIT=$(shell git rev-parse --short HEAD)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(shell [ ! -z $(TRAVIS) ] && [ "$(TRAVIS_PULL_REQUEST)" = "false" ] && [ "$(TRAVIS_BRANCH)" = "$(MAIN_BRANCH)" ] && echo true), true)
|
||||||
|
MQ_MANIFEST_TAG_SUFFIX=.$(TIMESTAMPFLAT).$(GIT_COMMIT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
PATH_TO_MQ_TAG_CACHE=$(TRAVIS_BUILD_DIR)/.tagcache
|
||||||
|
ifneq "$(TRAVIS)" "$(EMPTY)"
|
||||||
|
ifneq ("$(wildcard $(PATH_TO_MQ_TAG_CACHE))","")
|
||||||
|
include $(PATH_TO_MQ_TAG_CACHE)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
MQ_AMD64_TAG=$(MQ_MANIFEST_TAG)-amd64
|
||||||
|
MQ_S390X_TAG?=$(MQ_MANIFEST_TAG)-s390x
|
||||||
|
|
||||||
|
# end image tagging
|
||||||
|
|
||||||
MQ_IMAGE_FULL_RELEASE_NAME=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
|
MQ_IMAGE_FULL_RELEASE_NAME=$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
|
||||||
MQ_IMAGE_DEV_FULL_RELEASE_NAME=$(MQ_IMAGE_DEVSERVER):$(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_AMD64_TAG)
|
||||||
|
MQ_IMAGE_DEVSERVER_S390X=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEVSERVER):$(MQ_S390X_TAG)
|
||||||
|
MQ_IMAGE_ADVANCEDSERVER_AMD64=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_AMD64_TAG)
|
||||||
|
MQ_IMAGE_ADVANCEDSERVER_S390X=$(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_ADVANCEDSERVER):$(MQ_S390X_TAG)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Build targets
|
# Build targets
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -156,6 +193,9 @@ test-all: build-devjmstest test-devserver test-advancedserver
|
|||||||
.PHONY: devserver
|
.PHONY: devserver
|
||||||
devserver: build-devserver build-devjmstest test-devserver
|
devserver: build-devserver build-devjmstest test-devserver
|
||||||
|
|
||||||
|
.PHONY: advancedserver
|
||||||
|
advancedserver: build-advancedserver test-advancedserver
|
||||||
|
|
||||||
# Build incubating components
|
# Build incubating components
|
||||||
.PHONY: incubating
|
.PHONY: incubating
|
||||||
incubating: build-explorer
|
incubating: build-explorer
|
||||||
@@ -163,25 +203,48 @@ incubating: build-explorer
|
|||||||
downloads/$(MQ_ARCHIVE_DEV):
|
downloads/$(MQ_ARCHIVE_DEV):
|
||||||
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
|
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced for Developers "$(MQ_VERSION)$(END)))
|
||||||
mkdir -p downloads
|
mkdir -p downloads
|
||||||
|
ifneq "$(BUILD_RSYNC_SERVER)" "$(EMPTY)"
|
||||||
|
# Use key which is not stored in the repository to fetch the files from the fileserver
|
||||||
|
curl -L $(BUILD_RSYNC_ENCRYPTED_KEY_URL) -o ./host.key.gpg
|
||||||
|
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --batch --passphrase-fd 0 ./host.key.gpg
|
||||||
|
chmod 600 ./host.key
|
||||||
|
rsync -rv -e "ssh -o BatchMode=yes -q -o StrictHostKeyChecking=no -i ./host.key" --include="*/" --include="*.tar.gz" --exclude="*" $(BUILD_RSYNC_USER)@$(BUILD_RSYNC_SERVER):"$(BUILD_RSYNC_PATH)" downloads/$(MQ_ARCHIVE_DEV)
|
||||||
|
-@rm host.key.gpg host.key
|
||||||
|
else
|
||||||
ifneq "$(MQ_ARCHIVE_REPOSITORY_DEV)" "$(EMPTY)"
|
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)
|
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY_DEV)" -o downloads/$(MQ_ARCHIVE_DEV)
|
||||||
else
|
else
|
||||||
curl -L https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_ARCHIVE_DEV) -o downloads/$(MQ_ARCHIVE_DEV)
|
curl -L https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/$(MQ_ARCHIVE_DEV) -o downloads/$(MQ_ARCHIVE_DEV)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
downloads/$(MQ_ARCHIVE):
|
downloads/$(MQ_ARCHIVE):
|
||||||
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced "$(MQ_VERSION)$(END)))
|
$(info $(SPACER)$(shell printf $(TITLE)"Downloading IBM MQ Advanced "$(MQ_VERSION)$(END)))
|
||||||
mkdir -p downloads
|
mkdir -p downloads
|
||||||
|
ifneq "$(BUILD_RSYNC_SERVER)" "$(EMPTY)"
|
||||||
|
# Use key which is not stored in the repository to fetch the files from the fileserver
|
||||||
|
-@rm host.key.gpg host.key
|
||||||
|
curl -L $(BUILD_RSYNC_ENCRYPTED_KEY_URL) -o ./host.key.gpg
|
||||||
|
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --batch --passphrase-fd 0 ./host.key.gpg
|
||||||
|
chmod 600 ./host.key
|
||||||
|
rsync -rv -e "ssh -o BatchMode=yes -q -o StrictHostKeyChecking=no -i ./host.key" --include="*/" --include="*.tar.gz" --exclude="*" $(BUILD_RSYNC_USER)@$(BUILD_RSYNC_SERVER):"$(BUILD_RSYNC_PATH)" downloads/$(MQ_ARCHIVE)
|
||||||
|
-@rm host.key.gpg host.key
|
||||||
|
else
|
||||||
ifneq "$(MQ_ARCHIVE_REPOSITORY)" "$(EMPTY)"
|
ifneq "$(MQ_ARCHIVE_REPOSITORY)" "$(EMPTY)"
|
||||||
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY)" -o downloads/$(MQ_ARCHIVE)
|
curl -u $(MQ_ARCHIVE_REPOSITORY_USER):$(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -X GET "$(MQ_ARCHIVE_REPOSITORY)" -o downloads/$(MQ_ARCHIVE)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: downloads
|
.PHONY: downloads
|
||||||
downloads: downloads/$(MQ_ARCHIVE_DEV) downloads/$(MQ_SDK_ARCHIVE)
|
downloads: downloads/$(MQ_ARCHIVE_DEV) downloads/$(MQ_SDK_ARCHIVE)
|
||||||
|
|
||||||
|
.PHONY: cache-mq-tag
|
||||||
|
cache-mq-tag:
|
||||||
|
@printf "MQ_MANIFEST_TAG=$(MQ_MANIFEST_TAG)\n" | tee $(PATH_TO_MQ_TAG_CACHE)
|
||||||
|
|
||||||
# Vendor Go dependencies for the Docker tests
|
# Vendor Go dependencies for the Docker tests
|
||||||
test/docker/vendor:
|
test/docker/vendor:
|
||||||
cd test/docker && dep ensure -vendor-only
|
cd test/docker && go mod vendor
|
||||||
|
|
||||||
# Shortcut to just run the unit tests
|
# Shortcut to just run the unit tests
|
||||||
.PHONY: test-unit
|
.PHONY: test-unit
|
||||||
@@ -192,10 +255,10 @@ test-unit:
|
|||||||
test-advancedserver: test/docker/vendor
|
test-advancedserver: test/docker/vendor
|
||||||
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
||||||
docker inspect $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)
|
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
|
.PHONY: build-devjmstest
|
||||||
build-devjmstest:
|
build-devjmstest: registry-login
|
||||||
$(info $(SPACER)$(shell printf $(TITLE)"Build JMS tests for developer config"$(END)))
|
$(info $(SPACER)$(shell printf $(TITLE)"Build JMS tests for developer config"$(END)))
|
||||||
cd test/messaging && docker build --tag $(DEV_JMS_IMAGE) .
|
cd test/messaging && docker build --tag $(DEV_JMS_IMAGE) .
|
||||||
|
|
||||||
@@ -203,7 +266,7 @@ build-devjmstest:
|
|||||||
test-devserver: test/docker/vendor
|
test-devserver: test/docker/vendor
|
||||||
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_DEVSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_DEVSERVER):$(MQ_TAG) on $(shell docker --version)"$(END)))
|
||||||
docker inspect $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)
|
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
|
.PHONY: coverage
|
||||||
coverage:
|
coverage:
|
||||||
@@ -235,18 +298,16 @@ test-advancedserver-cover: test/docker/vendor coverage
|
|||||||
# Build an MQ image. The commands used are slightly different between Docker and Podman
|
# Build an MQ image. The commands used are slightly different between Docker and Podman
|
||||||
define build-mq
|
define build-mq
|
||||||
$(if $(findstring docker,$(COMMAND)), @docker network create build,)
|
$(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,)
|
$(if $(findstring docker,$(COMMAND)), @docker run --rm --name $(BUILD_SERVER_CONTAINER) --network build --network-alias build --volume $(DOWNLOADS_DIR):/opt/app-root/src:ro --detach registry.redhat.io/ubi8/nginx-118 nginx -g "daemon off;",)
|
||||||
$(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))
|
$(eval EXTRA_ARGS=$(if $(findstring docker,$(COMMAND)), --network build --build-arg MQ_URL=http://build:8080/$4, --volume $(DOWNLOADS_DIR):/var/downloads --build-arg MQ_URL=file:///var/downloads/$4))
|
||||||
# Build the new image
|
# Build the new image
|
||||||
$(COMMAND) build \
|
$(COMMAND) build \
|
||||||
--tag $1:$2 \
|
--tag $1:$2 \
|
||||||
--file $3 \
|
--file $3 \
|
||||||
$(EXTRA_ARGS) \
|
$(EXTRA_ARGS) \
|
||||||
--build-arg MQ_PACKAGES="$(MQ_PACKAGES)" \
|
|
||||||
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
|
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
|
||||||
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
|
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
|
||||||
--build-arg IMAGE_TAG="$1:$2" \
|
--build-arg IMAGE_TAG="$1:$2" \
|
||||||
--build-arg MQM_UID=$(MQM_UID) \
|
|
||||||
--label version=$(MQ_VERSION) \
|
--label version=$(MQ_VERSION) \
|
||||||
--label name=$1 \
|
--label name=$1 \
|
||||||
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
|
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
|
||||||
@@ -288,7 +349,7 @@ build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) comma
|
|||||||
build-devserver-host: build-devserver
|
build-devserver-host: build-devserver
|
||||||
|
|
||||||
.PHONY: build-devserver
|
.PHONY: build-devserver
|
||||||
build-devserver: registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
|
build-devserver: registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
|
||||||
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)"$(END)))
|
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)"$(END)))
|
||||||
$(call build-mq,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE_DEV),mq-dev-server)
|
$(call build-mq,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE_DEV),mq-dev-server)
|
||||||
|
|
||||||
@@ -321,7 +382,6 @@ log-build-vars:
|
|||||||
@echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER)
|
@echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER)
|
||||||
@echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER)
|
@echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER)
|
||||||
@echo COMMAND=$(COMMAND)
|
@echo COMMAND=$(COMMAND)
|
||||||
@echo MQM_UID=$(MQM_UID)
|
|
||||||
@echo REGISTRY_USER=$(REGISTRY_USER)
|
@echo REGISTRY_USER=$(REGISTRY_USER)
|
||||||
|
|
||||||
.PHONY: log-build-env
|
.PHONY: log-build-env
|
||||||
@@ -368,6 +428,30 @@ pull-devserver:
|
|||||||
$(COMMAND) pull $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME)
|
$(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)
|
$(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)))
|
||||||
|
ifneq "$(LTS)" "true"
|
||||||
|
$(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))
|
||||||
|
$(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)))
|
||||||
|
endif
|
||||||
|
$(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_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)))
|
||||||
|
ifneq "$(LTS)" "true"
|
||||||
|
$(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))
|
||||||
|
endif
|
||||||
|
$(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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf ./coverage
|
rm -rf ./coverage
|
||||||
@@ -378,6 +462,12 @@ clean:
|
|||||||
install-build-deps:
|
install-build-deps:
|
||||||
ARCH=$(ARCH) ./install-build-deps.sh
|
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
|
.PHONY: build-cov
|
||||||
build-cov:
|
build-cov:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
@@ -397,7 +487,8 @@ lint: $(addsuffix /$(wildcard *.go), $(GO_PKG_DIRS))
|
|||||||
golint -set_exit_status $(sort $(dir $(wildcard $(addsuffix /*/*.go, $(GO_PKG_DIRS)))))
|
golint -set_exit_status $(sort $(dir $(wildcard $(addsuffix /*/*.go, $(GO_PKG_DIRS)))))
|
||||||
|
|
||||||
.PHONY: gosec
|
.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 ;\
|
@gosec -fmt=json -out=gosec_results.json cmd/... internal/... 2> /dev/null ;\
|
||||||
cat "gosec_results.json" ;\
|
cat "gosec_results.json" ;\
|
||||||
cat gosec_results.json | grep HIGH | grep severity > /dev/null ;\
|
cat gosec_results.json | grep HIGH | grep severity > /dev/null ;\
|
||||||
@@ -423,3 +514,16 @@ gosec: $(info $(SPACER)$(shell printf "Running gosec test"$(END)))
|
|||||||
fi ;\
|
fi ;\
|
||||||
|
|
||||||
include formatting.mk
|
include formatting.mk
|
||||||
|
|
||||||
|
.PHONY: update-release-information
|
||||||
|
update-release-information:
|
||||||
|
sed -i.bak 's/ARG MQ_URL=.*-LinuxX64.tar.gz"/ARG MQ_URL="https:\/\/public.dhe.ibm.com\/ibmdl\/export\/pub\/software\/websphere\/messaging\/mqadv\/$(MQ_VERSION)-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"/g' Dockerfile-server && rm Dockerfile-server.bak
|
||||||
|
$(eval MQ_VERSION_1=$(shell echo '${MQ_VERSION}' | rev | cut -c 3- | rev))
|
||||||
|
sed -i.bak 's/IBM_MQ_.*_LINUX_X86-64_NOINST.tar.gz/IBM_MQ_${MQ_VERSION_1}_LINUX_X86-64_NOINST.tar.gz/g' docs/building.md && rm docs/building.md.bak
|
||||||
|
sed -i.bak 's/ibm-mqadvanced-server:.*-amd64/ibm-mqadvanced-server:$(MQ_VERSION)-amd64/g' docs/security.md
|
||||||
|
sed -i.bak 's/ibm-mqadvanced-server-dev.*-amd64/ibm-mqadvanced-server-dev:$(MQ_VERSION)-amd64/g' docs/security.md && rm docs/security.md.bak
|
||||||
|
sed -i.bak 's/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:.*-amd64/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:$(MQ_VERSION)-amd64/g' docs/testing.md && rm docs/testing.md.bak
|
||||||
|
$(eval MQ_VERSION_2=$(shell echo '${MQ_VERSION_1}' | rev | cut -c 3- | rev))
|
||||||
|
sed -i.bak 's/knowledgecenter\/SSFKSJ_.*\/com/knowledgecenter\/SSFKSJ_${MQ_VERSION_2}.0\/com/g' docs/usage.md && rm docs/usage.md.bak
|
||||||
|
$(eval MQ_VERSION_3=$(shell echo '${MQ_VERSION_1}' | sed "s/\.//g"))
|
||||||
|
sed -i.bak 's/MQ_..._ARCHIVE_REPOSITORY/MQ_${MQ_VERSION_3}_ARCHIVE_REPOSITORY/g' .travis.yml && rm .travis.yml.bak
|
||||||
|
|||||||
12650
NOTICES.txt
12650
NOTICES.txt
File diff suppressed because it is too large
Load Diff
@@ -44,11 +44,12 @@ 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).
|
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:
|
Licenses for the products installed within the images are as follows:
|
||||||
|
|
||||||
- [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BBZHCQ) (International License Agreement for Non-Warranted Programs). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
|
- [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BYHCL7) (International License Agreement for Non-Warranted Programs). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
|
||||||
- [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BGMHFW) (International Program License Agreement). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
|
- [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BZDDDY) (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.
|
Note: The IBM MQ Advanced for Developers license does not permit further distribution and the terms restrict usage to a developer machine.
|
||||||
|
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
© Copyright IBM Corporation 2015, 2019
|
© Copyright IBM Corporation 2015, 2021
|
||||||
|
|||||||
50
authservice/mqhtpass/Makefile
Normal file
50
authservice/mqhtpass/Makefile
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# © 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.
|
||||||
|
# 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 Makefile expects the following to be installed:
|
||||||
|
# - gcc
|
||||||
|
# - ldd
|
||||||
|
# - MQ SDK (mqm_r library, plus header files)
|
||||||
|
# - Apache Portable Runtime (apr-1 and aprutil-1 libraries, plus header files)
|
||||||
|
|
||||||
|
SRC_DIR = src
|
||||||
|
BUILD_DIR = ./build
|
||||||
|
|
||||||
|
# Flags passed to the C compiler. Need to use gnu11 to get POSIX functions needed for file locking.
|
||||||
|
CFLAGS += -std=gnu11 -fPIC -Wall -m64
|
||||||
|
|
||||||
|
LIB_APR = -L/usr/lib64 -lapr-1 -laprutil-1
|
||||||
|
LIB_MQ = -L/opt/mqm/lib64 -lmqm_r
|
||||||
|
|
||||||
|
all: $(BUILD_DIR)/mqhtpass.so $(BUILD_DIR)/htpass_test
|
||||||
|
|
||||||
|
$(BUILD_DIR)/log.o : $(SRC_DIR)/log.c $(SRC_DIR)/log.h
|
||||||
|
mkdir -p ${dir $@}
|
||||||
|
gcc $(CFLAGS) -c $(SRC_DIR)/log.c -o $@
|
||||||
|
|
||||||
|
$(BUILD_DIR)/htpass.o : $(SRC_DIR)/htpass.c $(SRC_DIR)/htpass.h
|
||||||
|
mkdir -p ${dir $@}
|
||||||
|
gcc $(CFLAGS) -c $(SRC_DIR)/htpass.c -I /usr/include/apr-1 -o $@
|
||||||
|
|
||||||
|
$(BUILD_DIR)/htpass_test : $(BUILD_DIR)/htpass.o $(BUILD_DIR)/log.o
|
||||||
|
mkdir -p ${dir $@}
|
||||||
|
gcc $(CFLAGS) $(LIB_APR) -lpthread $(SRC_DIR)/htpass_test.c $^ -o $@
|
||||||
|
# Run HTPasswd tests, and print log if they fail
|
||||||
|
$@ || (cat htpass_test*.log && exit 1)
|
||||||
|
|
||||||
|
$(BUILD_DIR)/mqhtpass.so : $(BUILD_DIR)/log.o $(BUILD_DIR)/htpass.o
|
||||||
|
mkdir -p ${dir $@}
|
||||||
|
# NOTE: rpath for libapr will be different on Ubuntu
|
||||||
|
gcc $(CFLAGS) -I/opt/mqm/inc -D_REENTRANT $(LIB_APR) $(LIB_MQ) -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64 -shared $(SRC_DIR)/mqhtpass.c $^ -o $@
|
||||||
|
ldd $@
|
||||||
145
authservice/mqhtpass/src/htpass.c
Normal file
145
authservice/mqhtpass/src/htpass.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "htpass.h"
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <apr_general.h>
|
||||||
|
#include <apr_errno.h>
|
||||||
|
#include <apr_md5.h>
|
||||||
|
|
||||||
|
bool htpass_valid_file(char *filename)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
FILE *fp;
|
||||||
|
char *huser;
|
||||||
|
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
log_errorf("Error %d opening htpasswd file '%s'", errno, filename);
|
||||||
|
}
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
const size_t line_size = 1024;
|
||||||
|
char *line = malloc(line_size);
|
||||||
|
while (fgets(line, line_size, fp) != NULL)
|
||||||
|
{
|
||||||
|
char *saveptr;
|
||||||
|
// Need to use strtok_r to be safe for multiple threads
|
||||||
|
huser = strtok_r(line, ":", &saveptr);
|
||||||
|
if (strlen(huser) >= 12)
|
||||||
|
{
|
||||||
|
log_errorf("Invalid htpasswd file for use with IBM MQ. User '%s' is longer than twelve characters", huser);
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *find_hash(char *filename, char *user)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
FILE *fp;
|
||||||
|
char *huser;
|
||||||
|
char *hash;
|
||||||
|
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
log_errorf("Error %d opening htpasswd file '%s'", errno, filename);
|
||||||
|
}
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
const size_t line_size = 1024;
|
||||||
|
char *line = malloc(line_size);
|
||||||
|
while (fgets(line, line_size, fp) != NULL)
|
||||||
|
{
|
||||||
|
char *saveptr;
|
||||||
|
// Need to use strtok_r to be safe for multiple threads
|
||||||
|
huser = strtok_r(line, ":", &saveptr);
|
||||||
|
if (huser && (strcmp(user, huser) == 0))
|
||||||
|
{
|
||||||
|
// Make a duplicate of the string, because we'll be keeping it
|
||||||
|
hash = strdup(strtok_r(NULL, " \r\n\t", &saveptr));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
hash = NULL;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
int htpass_authenticate_user(char *filename, char *user, char *password)
|
||||||
|
{
|
||||||
|
char *hash = find_hash(filename, user);
|
||||||
|
int result = -1;
|
||||||
|
if (hash == NULL)
|
||||||
|
{
|
||||||
|
result = HTPASS_INVALID_USER;
|
||||||
|
log_debugf("User does not exist. user=%s", user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use the Apache Portable Runtime utilities to validate the password against the hash.
|
||||||
|
// Supports multiple hashing algorithms, but we should only be using bcrypt
|
||||||
|
apr_status_t status = apr_password_validate(password, hash);
|
||||||
|
// status is usually either APR_SUCCESS or APR_EMISMATCH
|
||||||
|
if (status == APR_SUCCESS)
|
||||||
|
{
|
||||||
|
result = HTPASS_VALID;
|
||||||
|
log_debugf("Correct password supplied. user=%s", user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = HTPASS_INVALID_PASSWORD;
|
||||||
|
log_debugf("Incorrect password supplied. user=%s", user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool htpass_valid_user(char *filename, char *user)
|
||||||
|
{
|
||||||
|
char *hash = find_hash(filename, user);
|
||||||
|
bool valid = false;
|
||||||
|
if (hash != NULL)
|
||||||
|
{
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
49
authservice/mqhtpass/src/htpass.h
Normal file
49
authservice/mqhtpass/src/htpass.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HTPASS_H
|
||||||
|
#define _HTPASS_H
|
||||||
|
|
||||||
|
#define HTPASS_VALID 0
|
||||||
|
#define HTPASS_INVALID_USER 1
|
||||||
|
#define HTPASS_INVALID_PASSWORD 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate an HTPasswd file for use with IBM MQ.
|
||||||
|
*
|
||||||
|
* @param filename the HTPasswd file
|
||||||
|
*/
|
||||||
|
_Bool htpass_valid_file(char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate a user, based on the supplied file name.
|
||||||
|
*
|
||||||
|
* @param filename the HTPasswd file
|
||||||
|
* @param user the user name to authenticate
|
||||||
|
* @param password the password of the user
|
||||||
|
* @return HTPASS_VALID, HTPASS_INVALID_USER or HTPASS_INVALID_PASSWORD
|
||||||
|
*/
|
||||||
|
int htpass_authenticate_user(char *filename, char *user, char *password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that a user exists in the password file.
|
||||||
|
*
|
||||||
|
* @param filename the HTPasswd file
|
||||||
|
* @param user the user name to validate
|
||||||
|
*/
|
||||||
|
_Bool htpass_valid_user(char *filename, char *user);
|
||||||
|
|
||||||
|
#endif
|
||||||
223
authservice/mqhtpass/src/htpass_test.c
Normal file
223
authservice/mqhtpass/src/htpass_test.c
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "htpass.h"
|
||||||
|
|
||||||
|
// Headers for multi-threaded tests
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// Start a test and log the function name
|
||||||
|
#define test_start() printf("=== RUN: %s\n", __func__)
|
||||||
|
|
||||||
|
// Indicate test has passed
|
||||||
|
#define test_pass() printf("--- PASS: %s\n", __func__)
|
||||||
|
|
||||||
|
// Indicate test has failed
|
||||||
|
void test_fail(const char *test_name)
|
||||||
|
{
|
||||||
|
printf("--- FAIL: %s\n", test_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Simple tests for file validation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void test_htpass_valid_file_ok()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int ok = htpass_valid_file("./src/htpass_test.htpasswd");
|
||||||
|
if (!ok)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_valid_file_too_long()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int ok = htpass_valid_file("./src/htpass_test_invalid.htpasswd");
|
||||||
|
if (ok)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Simple tests for authentication
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_fred_valid()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd");
|
||||||
|
printf("%s: fred - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_VALID)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_fred_invalid1()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd ");
|
||||||
|
printf("%s: fred - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_INVALID_PASSWORD)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_fred_invalid2()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "");
|
||||||
|
printf("%s: fred - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_INVALID_PASSWORD)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_fred_invalid3()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "clearlywrong");
|
||||||
|
printf("%s: fred - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_INVALID_PASSWORD)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_barney_valid()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "barney", "s3cret");
|
||||||
|
printf("%s: barney - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_VALID)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_htpass_authenticate_user_unknown()
|
||||||
|
{
|
||||||
|
test_start();
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "george", "s3cret");
|
||||||
|
printf("%s: barney - %d\n", __func__, rc);
|
||||||
|
if (rc != HTPASS_INVALID_USER)
|
||||||
|
test_fail(__func__);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Multi-threaded test
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define NUM_THREADS 5
|
||||||
|
// Number of tests to perform per thread. Higher numbers are more likely to trigger timing issue.
|
||||||
|
#define NUM_TESTS_PER_THREAD 1000
|
||||||
|
// Maximum number of JSON errors to report (log can get flooded)
|
||||||
|
#define MAX_JSON_ERRORS 10
|
||||||
|
|
||||||
|
// Authenticate multiple users, multiple times
|
||||||
|
void *authenticate_many_times(void *p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_TESTS_PER_THREAD; i++)
|
||||||
|
{
|
||||||
|
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "barney", "s3cret");
|
||||||
|
if (rc != HTPASS_VALID)
|
||||||
|
test_fail(__func__);
|
||||||
|
rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd");
|
||||||
|
if (rc != HTPASS_VALID)
|
||||||
|
test_fail(__func__);
|
||||||
|
}
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_log_file_valid(char *filename)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
printf("--- Checking log file is valid\n");
|
||||||
|
// Check that the JSON log file isn't corrupted
|
||||||
|
FILE *log = fopen(filename, "r");
|
||||||
|
if (log == NULL)
|
||||||
|
{
|
||||||
|
test_fail(__func__);
|
||||||
|
}
|
||||||
|
const size_t line_size = 1024;
|
||||||
|
char *line = malloc(line_size);
|
||||||
|
while (fgets(line, line_size, log) != NULL)
|
||||||
|
{
|
||||||
|
if ((line[0] != '{') && (errors < MAX_JSON_ERRORS))
|
||||||
|
{
|
||||||
|
printf("*** Invalid JSON detected: %s\n", line);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test authenticate_user with multiple threads, each doing many authentications
|
||||||
|
void test_htpass_authenticate_user_multithreaded(char *logfile)
|
||||||
|
{
|
||||||
|
pthread_t threads[NUM_THREADS];
|
||||||
|
int rc;
|
||||||
|
test_start();
|
||||||
|
// Re-initialize the log to use a file for the multi-threaded test
|
||||||
|
log_init(logfile);
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++)
|
||||||
|
{
|
||||||
|
printf("Creating thread %d\n", i);
|
||||||
|
rc = pthread_create(&threads[i], NULL, authenticate_many_times, NULL);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
printf("Error: Unable to create thread, %d\n", rc);
|
||||||
|
test_fail(__func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait for all the threads to complete
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++)
|
||||||
|
{
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
check_log_file_valid(logfile);
|
||||||
|
test_pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Turn on debugging for the tests
|
||||||
|
setenv("DEBUG", "true", true);
|
||||||
|
log_init("htpass_test.log");
|
||||||
|
test_htpass_valid_file_ok();
|
||||||
|
test_htpass_valid_file_too_long();
|
||||||
|
test_htpass_authenticate_user_fred_valid();
|
||||||
|
test_htpass_authenticate_user_fred_invalid1();
|
||||||
|
test_htpass_authenticate_user_fred_invalid2();
|
||||||
|
test_htpass_authenticate_user_fred_invalid3();
|
||||||
|
test_htpass_authenticate_user_barney_valid();
|
||||||
|
test_htpass_authenticate_user_unknown();
|
||||||
|
log_close();
|
||||||
|
|
||||||
|
// Call multi-threaded test last, because it re-initializes the log to use a file
|
||||||
|
test_htpass_authenticate_user_multithreaded("htpass_test_multithreaded.log");
|
||||||
|
}
|
||||||
2
authservice/mqhtpass/src/htpass_test.htpasswd
Normal file
2
authservice/mqhtpass/src/htpass_test.htpasswd
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fred:$2y$05$3Fp9epsqEwWOHdyj9Ngf9.qfX34kzc9zNrdQ7kac0GmcCvQjIkAwy
|
||||||
|
barney:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a
|
||||||
3
authservice/mqhtpass/src/htpass_test_invalid.htpasswd
Normal file
3
authservice/mqhtpass/src/htpass_test_invalid.htpasswd
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fred:$2y$05$3Fp9epsqEwWOHdyj9Ngf9.qfX34kzc9zNrdQ7kac0GmcCvQjIkAwy
|
||||||
|
barney:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a
|
||||||
|
namewhichisfartoolongformq:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a
|
||||||
152
authservice/mqhtpass/src/log.c
Normal file
152
authservice/mqhtpass/src/log.c
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int pid;
|
||||||
|
char hostname[255];
|
||||||
|
bool debug = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether debugging is enabled or not, using an environment variable.
|
||||||
|
*/
|
||||||
|
void init_debug(){
|
||||||
|
char *debug_env = getenv("DEBUG");
|
||||||
|
if (debug_env != NULL)
|
||||||
|
{
|
||||||
|
// Enable debug logging if the DEBUG environment variable is set
|
||||||
|
if (strncmp(debug_env, "true", 4) || strncmp(debug_env, "1", 1))
|
||||||
|
{
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function to initialize the log with the given file mode.
|
||||||
|
*/
|
||||||
|
int log_init_internal(char *filename, const char *mode)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
pid = getpid();
|
||||||
|
hostname[254] = '\0';
|
||||||
|
gethostname(hostname, 254);
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
fp = fopen(filename, "a");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
// Disable buffering for this file
|
||||||
|
setbuf(fp, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
init_debug();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_init_reset(char *filename)
|
||||||
|
{
|
||||||
|
// Open the log file for writing (overwrite if it already exists)
|
||||||
|
return log_init_internal(filename, "w");
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_init(char *filename)
|
||||||
|
{
|
||||||
|
// Open the log file file for appending
|
||||||
|
return log_init_internal(filename, "a");
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_init_file(FILE *f)
|
||||||
|
{
|
||||||
|
fp = f;
|
||||||
|
init_debug();
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_close()
|
||||||
|
{
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
fp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_printf(const char *source_file, int source_line, const char *level, const char *format, ...)
|
||||||
|
{
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
// If this is a DEBUG message, and debugging is off
|
||||||
|
if ((strncmp(level, "DEBUG", 5) == 0) && !debug)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buf[1024] = "";
|
||||||
|
char *cur = buf;
|
||||||
|
char* const end = buf + sizeof buf;
|
||||||
|
char date_buf[70];
|
||||||
|
struct tm *utc;
|
||||||
|
time_t t;
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
t = now.tv_sec;
|
||||||
|
t = time(NULL);
|
||||||
|
utc = gmtime(&t);
|
||||||
|
|
||||||
|
cur += snprintf(cur, end-cur, "{");
|
||||||
|
cur += snprintf(cur, end-cur, "\"loglevel\":\"%s\"", level);
|
||||||
|
// Print ISO-8601 time and date
|
||||||
|
if (strftime(date_buf, sizeof date_buf, "%FT%T", utc))
|
||||||
|
{
|
||||||
|
// Round microseconds down to milliseconds, for consistency
|
||||||
|
cur += snprintf(cur, end-cur, ", \"ibm_datetime\":\"%s.%03ldZ\"", date_buf, now.tv_usec / 1000);
|
||||||
|
}
|
||||||
|
cur += snprintf(cur, end-cur, ", \"ibm_processId\":\"%d\"", pid);
|
||||||
|
cur += snprintf(cur, end-cur, ", \"host\":\"%s\"", hostname);
|
||||||
|
cur += snprintf(cur, end-cur, ", \"module\":\"%s:%d\"", source_file, source_line);
|
||||||
|
cur += snprintf(cur, end-cur, ", \"message\":\"");
|
||||||
|
|
||||||
|
if (strncmp(level, "DEBUG", 5) == 0)
|
||||||
|
{
|
||||||
|
// Add a prefix on any debug messages
|
||||||
|
cur += snprintf(cur, end-cur, "mqhtpass: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print log message, using varargs
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
cur += vsnprintf(cur, end-cur, format, args);
|
||||||
|
va_end(args);
|
||||||
|
cur += snprintf(cur, end-cur, "\"}\n");
|
||||||
|
|
||||||
|
// Important: Just do one file write, to prevent problems with multi-threading.
|
||||||
|
// This only works if the log message is not too long for the buffer.
|
||||||
|
fprintf(fp, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
63
authservice/mqhtpass/src/log.h
Normal file
63
authservice/mqhtpass/src/log.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LOG_H
|
||||||
|
#define _LOG_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the log to use the given file name, wiping any existing contents.
|
||||||
|
*/
|
||||||
|
int log_init_reset(char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the log to use the given file name.
|
||||||
|
*/
|
||||||
|
int log_init(char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the log with an existing file handle.
|
||||||
|
*/
|
||||||
|
void log_init_file(FILE *f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a message to the log file, based on a printf format string.
|
||||||
|
*
|
||||||
|
* @param source_file the name of the source code file submitting this log message
|
||||||
|
* @param source_line the line of code in the source file
|
||||||
|
* @param level the log level, one of "DEBUG", "INFO" or "ERROR"
|
||||||
|
* @param format the printf format string for the message
|
||||||
|
*/
|
||||||
|
void log_printf(const char *source_file, int source_line, const char *level, const char *format, ...);
|
||||||
|
|
||||||
|
void log_close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variadic macro to write an informational message to the log file, based on a printf format string.
|
||||||
|
*/
|
||||||
|
#define log_infof(format,...) log_printf(__FILE__, __LINE__, "INFO", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variadic macro to write an error message to the log file, based on a printf format string.
|
||||||
|
*/
|
||||||
|
#define log_errorf(format,...) log_printf(__FILE__, __LINE__, "ERROR", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variadic macro to write a debug message to the log file, based on a printf format string.
|
||||||
|
*/
|
||||||
|
#define log_debugf(format,...) log_printf(__FILE__, __LINE__, "DEBUG", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
351
authservice/mqhtpass/src/mqhtpass.c
Normal file
351
authservice/mqhtpass/src/mqhtpass.c
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cmqec.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "htpass.h"
|
||||||
|
|
||||||
|
// Declare the internal functions that implement the interface
|
||||||
|
MQZ_INIT_AUTHORITY MQStart;
|
||||||
|
static MQZ_AUTHENTICATE_USER mqhtpass_authenticate_user;
|
||||||
|
static MQZ_FREE_USER mqhtpass_free_user;
|
||||||
|
static MQZ_TERM_AUTHORITY mqhtpass_terminate;
|
||||||
|
|
||||||
|
#define LOG_FILE "/var/mqm/errors/mqhtpass.json"
|
||||||
|
#define HTPASSWD_FILE "/etc/mqm/mq.htpasswd"
|
||||||
|
#define NAME "MQ Advanced for Developers custom authentication service"
|
||||||
|
|
||||||
|
static char *trim(char *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization and entrypoint for the dynamically loaded
|
||||||
|
* authorization installable service. It registers the addresses of the
|
||||||
|
* other functions which are to be called by the queue manager.
|
||||||
|
*
|
||||||
|
* This function is called whenever the module is loaded. The Options
|
||||||
|
* field will show whether it's a PRIMARY (i.e. during qmgr startup) or
|
||||||
|
* SECONDARY.
|
||||||
|
*/
|
||||||
|
void MQENTRY MQStart(
|
||||||
|
MQHCONFIG hc,
|
||||||
|
MQLONG Options,
|
||||||
|
MQCHAR48 QMgrName,
|
||||||
|
MQLONG ComponentDataLength,
|
||||||
|
PMQBYTE ComponentData,
|
||||||
|
PMQLONG Version,
|
||||||
|
PMQLONG pCompCode,
|
||||||
|
PMQLONG pReason)
|
||||||
|
{
|
||||||
|
MQLONG CC = MQCC_OK;
|
||||||
|
MQLONG Reason = MQRC_NONE;
|
||||||
|
int log_rc = 0;
|
||||||
|
|
||||||
|
if (Options == MQZIO_PRIMARY)
|
||||||
|
{
|
||||||
|
// Reset the log file. The file could still get large if debug is turned on,
|
||||||
|
// but this is a simpler solution for now.
|
||||||
|
log_rc = log_init_reset(LOG_FILE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_rc = log_init(LOG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_rc != 0)
|
||||||
|
{
|
||||||
|
CC = MQCC_FAILED;
|
||||||
|
Reason = MQRC_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Options == MQZIO_PRIMARY)
|
||||||
|
{
|
||||||
|
log_infof("Initializing %s", NAME);
|
||||||
|
}
|
||||||
|
log_debugf("MQStart options=%s qmgr=%s", ((Options == MQZIO_SECONDARY) ? "Secondary" : "Primary"), trim(QMgrName));
|
||||||
|
|
||||||
|
if (!htpass_valid_file(HTPASSWD_FILE))
|
||||||
|
{
|
||||||
|
CC = MQCC_FAILED;
|
||||||
|
Reason = MQRC_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the functions to use for each entry point
|
||||||
|
if (CC == MQCC_OK)
|
||||||
|
{
|
||||||
|
hc->MQZEP_Call(hc, MQZID_INIT_AUTHORITY, (PMQFUNC)MQStart, &CC, &Reason);
|
||||||
|
}
|
||||||
|
if (CC == MQCC_OK)
|
||||||
|
{
|
||||||
|
hc->MQZEP_Call(hc, MQZID_TERM_AUTHORITY, (PMQFUNC)mqhtpass_terminate, &CC, &Reason);
|
||||||
|
}
|
||||||
|
if (CC == MQCC_OK)
|
||||||
|
{
|
||||||
|
hc->MQZEP_Call(hc, MQZID_AUTHENTICATE_USER, (PMQFUNC)mqhtpass_authenticate_user, &CC, &Reason);
|
||||||
|
}
|
||||||
|
if (CC == MQCC_OK)
|
||||||
|
{
|
||||||
|
hc->MQZEP_Call(hc, MQZID_FREE_USER, (PMQFUNC)mqhtpass_free_user, &CC, &Reason);
|
||||||
|
}
|
||||||
|
*Version = MQZAS_VERSION_5;
|
||||||
|
*pCompCode = CC;
|
||||||
|
*pReason = Reason;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called during the connection of any application which supplies an MQCSP (Connection Security Parameters).
|
||||||
|
* This is the usual case.
|
||||||
|
* See https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q095610_.html
|
||||||
|
*/
|
||||||
|
static void MQENTRY mqhtpass_authenticate_user_csp(
|
||||||
|
PMQCHAR pQMgrName,
|
||||||
|
PMQCSP pSecurityParms,
|
||||||
|
PMQZAC pApplicationContext,
|
||||||
|
PMQZIC pIdentityContext,
|
||||||
|
PMQPTR pCorrelationPtr,
|
||||||
|
PMQBYTE pComponentData,
|
||||||
|
PMQLONG pContinuation,
|
||||||
|
PMQLONG pCompCode,
|
||||||
|
PMQLONG pReason)
|
||||||
|
{
|
||||||
|
char *csp_user = NULL;
|
||||||
|
char *csp_pass = NULL;
|
||||||
|
|
||||||
|
// Firstly, create null-terminated strings from the user credentials in the MQ CSP object
|
||||||
|
csp_user = malloc(pSecurityParms->CSPUserIdLength + 1);
|
||||||
|
if (!csp_user)
|
||||||
|
{
|
||||||
|
log_errorf("%s is unable to allocate memory for a user", NAME);
|
||||||
|
*pCompCode = MQCC_FAILED;
|
||||||
|
*pReason = MQRC_SERVICE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strncpy(csp_user, pSecurityParms->CSPUserIdPtr, pSecurityParms->CSPUserIdLength);
|
||||||
|
csp_user[pSecurityParms->CSPUserIdLength] = 0;
|
||||||
|
csp_pass = malloc((pSecurityParms->CSPPasswordLength + 1));
|
||||||
|
if (!csp_pass)
|
||||||
|
{
|
||||||
|
log_errorf("%s is unable to allocate memory for a password", NAME);
|
||||||
|
*pCompCode = MQCC_FAILED;
|
||||||
|
*pReason = MQRC_SERVICE_ERROR;
|
||||||
|
if (csp_user)
|
||||||
|
{
|
||||||
|
free(csp_user);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strncpy(csp_pass, pSecurityParms->CSPPasswordPtr, pSecurityParms->CSPPasswordLength);
|
||||||
|
csp_pass[pSecurityParms->CSPPasswordLength] = 0;
|
||||||
|
log_debugf("%s with CSP user set. user=%s", __func__, csp_user);
|
||||||
|
int auth_result = htpass_authenticate_user(HTPASSWD_FILE, csp_user, csp_pass);
|
||||||
|
|
||||||
|
if (auth_result == HTPASS_VALID)
|
||||||
|
{
|
||||||
|
// An OK completion code means MQ will accept this user is authenticated
|
||||||
|
*pCompCode = MQCC_OK;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
// Tell the queue manager to stop trying other authorization services.
|
||||||
|
*pContinuation = MQZCI_STOP;
|
||||||
|
memcpy(pIdentityContext->UserIdentifier, csp_user, sizeof(pIdentityContext->UserIdentifier));
|
||||||
|
log_debugf("Authenticated user=%s", pIdentityContext->UserIdentifier);
|
||||||
|
}
|
||||||
|
// If the htpasswd file does not have an entry for this user
|
||||||
|
else if (auth_result == HTPASS_INVALID_USER)
|
||||||
|
{
|
||||||
|
*pCompCode = MQCC_WARNING;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
// Tell the queue manager to continue trying other authorization services, as they might have the user.
|
||||||
|
*pContinuation = MQZCI_CONTINUE;
|
||||||
|
log_debugf(
|
||||||
|
"User authentication failed due to invalid user. user=%s effuser=%s applname=%s csp_user=%s cc=%d reason=%d",
|
||||||
|
trim(pIdentityContext->UserIdentifier),
|
||||||
|
trim(pApplicationContext->EffectiveUserID),
|
||||||
|
trim(pApplicationContext->ApplName),
|
||||||
|
trim(csp_user),
|
||||||
|
*pCompCode,
|
||||||
|
*pReason);
|
||||||
|
}
|
||||||
|
// If the htpasswd file has an entry for this user, but the password supplied is incorrect
|
||||||
|
else if (auth_result == HTPASS_INVALID_PASSWORD)
|
||||||
|
{
|
||||||
|
*pCompCode = MQCC_WARNING;
|
||||||
|
*pReason = MQRC_NOT_AUTHORIZED;
|
||||||
|
// Tell the queue manager to stop trying other authorization services.
|
||||||
|
*pContinuation = MQZCI_STOP;
|
||||||
|
log_debugf(
|
||||||
|
"User authentication failed due to invalid password. user=%s effuser=%s applname=%s csp_user=%s cc=%d reason=%d",
|
||||||
|
trim(pIdentityContext->UserIdentifier),
|
||||||
|
trim(pApplicationContext->EffectiveUserID),
|
||||||
|
trim(pApplicationContext->ApplName),
|
||||||
|
trim(csp_user),
|
||||||
|
*pCompCode,
|
||||||
|
*pReason);
|
||||||
|
}
|
||||||
|
if (csp_user)
|
||||||
|
{
|
||||||
|
free(csp_user);
|
||||||
|
}
|
||||||
|
if (csp_pass)
|
||||||
|
{
|
||||||
|
free(csp_pass);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called during the connection of any application.
|
||||||
|
* For more information on the parameters, see https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q110090_.html
|
||||||
|
*/
|
||||||
|
static void MQENTRY mqhtpass_authenticate_user(
|
||||||
|
PMQCHAR pQMgrName,
|
||||||
|
PMQCSP pSecurityParms,
|
||||||
|
PMQZAC pApplicationContext,
|
||||||
|
PMQZIC pIdentityContext,
|
||||||
|
PMQPTR pCorrelationPtr,
|
||||||
|
PMQBYTE pComponentData,
|
||||||
|
PMQLONG pContinuation,
|
||||||
|
PMQLONG pCompCode,
|
||||||
|
PMQLONG pReason)
|
||||||
|
{
|
||||||
|
char *spuser = NULL;
|
||||||
|
char *sppass = NULL;
|
||||||
|
// By default, return a warning, which indicates to MQ that this
|
||||||
|
// authorization service hasn't authenticated the user.
|
||||||
|
*pCompCode = MQCC_WARNING;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
// By default, tell the queue manager to continue trying other
|
||||||
|
// authorization services.
|
||||||
|
*pContinuation = MQZCI_CONTINUE;
|
||||||
|
|
||||||
|
if ((pSecurityParms->AuthenticationType) == MQCSP_AUTH_USER_ID_AND_PWD)
|
||||||
|
{
|
||||||
|
mqhtpass_authenticate_user_csp(pQMgrName, pSecurityParms, pApplicationContext, pIdentityContext, pCorrelationPtr, pComponentData, pContinuation, pCompCode, pReason);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Password not supplied, so just check that the user ID is valid
|
||||||
|
spuser = malloc(sizeof(PMQCHAR12) + 1);
|
||||||
|
if (!spuser)
|
||||||
|
{
|
||||||
|
log_errorf("%s is unable to allocate memory to check a user", NAME);
|
||||||
|
*pCompCode = MQCC_FAILED;
|
||||||
|
*pReason = MQRC_SERVICE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strncpy(spuser, pApplicationContext->EffectiveUserID, strlen(pApplicationContext->EffectiveUserID));
|
||||||
|
spuser[sizeof(PMQCHAR12)] = 0;
|
||||||
|
log_debugf("%s without CSP user set. effectiveuid=%s env=%d, callertype=%d, type=%d, accttoken=%d applidentitydata=%d", __func__, spuser, pApplicationContext->Environment, pApplicationContext->CallerType, pApplicationContext->AuthenticationType, pIdentityContext->AccountingToken, pIdentityContext->ApplIdentityData);
|
||||||
|
if (strncmp(spuser, "mqm", 3) == 0)
|
||||||
|
{
|
||||||
|
// Special case: pass the "mqm" user on for validation up the chain
|
||||||
|
// A warning in the completion code means MQ will pass this to other authorization services
|
||||||
|
*pCompCode = MQCC_WARNING;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
*pContinuation = MQZCI_CONTINUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool valid_user = htpass_valid_user(HTPASSWD_FILE, spuser);
|
||||||
|
if (valid_user)
|
||||||
|
{
|
||||||
|
// An OK completion code means MQ will accept this user is authenticated
|
||||||
|
*pCompCode = MQCC_OK;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
*pContinuation = MQZCI_STOP;
|
||||||
|
memcpy(pIdentityContext->UserIdentifier, spuser, sizeof(pIdentityContext->UserIdentifier));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_debugf(
|
||||||
|
"User authentication failed user=%s effuser=%s applname=%s cspuser=%s cc=%d reason=%d",
|
||||||
|
trim(pIdentityContext->UserIdentifier),
|
||||||
|
trim(pApplicationContext->EffectiveUserID),
|
||||||
|
trim(pApplicationContext->ApplName),
|
||||||
|
trim(spuser),
|
||||||
|
*pCompCode,
|
||||||
|
*pReason);
|
||||||
|
}
|
||||||
|
if (spuser)
|
||||||
|
{
|
||||||
|
free(spuser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called during MQDISC, as the inverse of the call to authenticate.
|
||||||
|
*/
|
||||||
|
static void MQENTRY mqhtpass_free_user(
|
||||||
|
PMQCHAR pQMgrName,
|
||||||
|
PMQZFP pFreeParms,
|
||||||
|
PMQBYTE pComponentData,
|
||||||
|
PMQLONG pContinuation,
|
||||||
|
|
||||||
|
PMQLONG pCompCode,
|
||||||
|
PMQLONG pReason)
|
||||||
|
{
|
||||||
|
log_debugf("mqhtpass_freeuser()");
|
||||||
|
*pCompCode = MQCC_WARNING;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
*pContinuation = MQZCI_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the authorization service is terminated.
|
||||||
|
*/
|
||||||
|
static void MQENTRY mqhtpass_terminate(
|
||||||
|
MQHCONFIG hc,
|
||||||
|
MQLONG Options,
|
||||||
|
PMQCHAR pQMgrName,
|
||||||
|
PMQBYTE pComponentData,
|
||||||
|
PMQLONG pCompCode,
|
||||||
|
PMQLONG pReason)
|
||||||
|
{
|
||||||
|
if (Options == MQZTO_PRIMARY)
|
||||||
|
{
|
||||||
|
log_infof("Terminating %s", NAME);
|
||||||
|
log_close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_debugf("Terminating secondary");
|
||||||
|
}
|
||||||
|
*pCompCode = MQCC_OK;
|
||||||
|
*pReason = MQRC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove trailing spaces from a string.
|
||||||
|
*/
|
||||||
|
static char *trim(char *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = strlen(s) - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (s[i] == ' ')
|
||||||
|
s[i] = 0;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2017, 2019
|
© Copyright IBM Corporation 2017, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -36,12 +36,12 @@ func queueManagerHealthy() (bool, error) {
|
|||||||
cmd := exec.Command("dspmq", "-n", "-m", name)
|
cmd := exec.Command("dspmq", "-n", "-m", name)
|
||||||
// Run the command and wait for completion
|
// Run the command and wait for completion
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
|
fmt.Printf("%s", out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return false, 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)") && !strings.Contains(string(out), "(REPLICA)") {
|
||||||
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the queue manager has a running listener
|
// Check if the queue manager has a running listener
|
||||||
if standby, _ := ready.IsRunningAsStandbyQM(name); !standby {
|
if active, _ := ready.IsRunningAsActiveQM(name); active {
|
||||||
conn, err := net.Dial("tcp", "127.0.0.1:1414")
|
conn, err := net.Dial("tcp", "127.0.0.1:1414")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -49,8 +49,13 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else if standby, _ := ready.IsRunningAsStandbyQM(name); standby {
|
||||||
fmt.Printf("Detected queue manager running in standby mode")
|
fmt.Printf("Detected queue manager running in standby mode")
|
||||||
os.Exit(10)
|
os.Exit(10)
|
||||||
|
} else if replica, _ := ready.IsRunningAsReplicaQM(name); replica {
|
||||||
|
fmt.Printf("Detected queue manager running in replica mode")
|
||||||
|
os.Exit(20)
|
||||||
|
} else {
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
58
cmd/chkmqstarted/main.go
Normal file
58
cmd/chkmqstarted/main.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// chkmqstarted checks that MQ has successfully started, by checking the output of the "dspmq" command
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||||
|
)
|
||||||
|
|
||||||
|
func queueManagerStarted() (bool, error) {
|
||||||
|
name, err := name.GetQueueManagerName()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Specify the queue manager name, just in case someone's created a second queue manager
|
||||||
|
// #nosec G204
|
||||||
|
cmd := exec.Command("dspmq", "-n", "-m", name)
|
||||||
|
// Run the command and wait for completion
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") && !strings.Contains(string(out), "(REPLICA)") {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
started, err := queueManagerStarted()
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
if !started {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -19,10 +19,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
"github.com/ibm-messaging/mq-container/internal/htpasswd"
|
||||||
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
||||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||||
"github.com/ibm-messaging/mq-container/pkg/name"
|
"github.com/ibm-messaging/mq-container/pkg/name"
|
||||||
@@ -30,27 +29,6 @@ import (
|
|||||||
|
|
||||||
var log *logger.Logger
|
var log *logger.Logger
|
||||||
|
|
||||||
func setPassword(user string, password string) error {
|
|
||||||
// #nosec G204
|
|
||||||
cmd := exec.Command("sudo", "chpasswd")
|
|
||||||
stdin, err := cmd.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(stdin, "%s:%s", user, password)
|
|
||||||
err = stdin.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Error closing password stdin: %v", err)
|
|
||||||
}
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
// Include the command output in the error
|
|
||||||
return fmt.Errorf("%v: %v", err.Error(), out)
|
|
||||||
}
|
|
||||||
log.Printf("Set password for \"%v\" user", user)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLogFormat() string {
|
func getLogFormat() string {
|
||||||
return os.Getenv("LOG_FORMAT")
|
return os.Getenv("LOG_FORMAT")
|
||||||
}
|
}
|
||||||
@@ -89,11 +67,6 @@ func configureLogger() error {
|
|||||||
return nil
|
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{}) {
|
func logTerminationf(format string, args ...interface{}) {
|
||||||
logTermination(fmt.Sprintf(format, args...))
|
logTermination(fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
@@ -125,16 +98,23 @@ func doMain() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
adminPassword, set := os.LookupEnv("MQ_ADMIN_PASSWORD")
|
adminPassword, set := os.LookupEnv("MQ_ADMIN_PASSWORD")
|
||||||
if set {
|
if !set {
|
||||||
err = setPassword("admin", adminPassword)
|
adminPassword = "passw0rd"
|
||||||
|
err = os.Setenv("MQ_ADMIN_PASSWORD", adminPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTerminationf("Error setting admin password: %v", err)
|
logTerminationf("Error setting admin password variable: %v", err)
|
||||||
return 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")
|
appPassword, set := os.LookupEnv("MQ_APP_PASSWORD")
|
||||||
if set {
|
if set {
|
||||||
err = setPassword("app", appPassword)
|
err = htpasswd.SetPassword("app", appPassword, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTerminationf("Error setting app password: %v", err)
|
logTerminationf("Error setting app password: %v", err)
|
||||||
return err
|
return err
|
||||||
@@ -147,18 +127,6 @@ func doMain() error {
|
|||||||
return err
|
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
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -17,14 +17,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func createVolume(dataPath string) error {
|
func createVolume(dataPath string) error {
|
||||||
fi, err := os.Stat(dataPath)
|
_, err := os.Stat(dataPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// #nosec G301
|
// #nosec G301
|
||||||
@@ -36,25 +32,5 @@ func createVolume(dataPath string) error {
|
|||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2017, 2019
|
© Copyright IBM Corporation 2017, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -60,8 +61,27 @@ func getLogFormat() string {
|
|||||||
return os.Getenv("LOG_FORMAT")
|
return os.Getenv("LOG_FORMAT")
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatSimple(datetime string, message string) string {
|
// formatBasic formats a log message parsed from JSON, as "basic" text
|
||||||
return fmt.Sprintf("%v %v\n", datetime, message)
|
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, ", "))
|
||||||
|
}
|
||||||
|
// Convert time zone information from some logs (e.g. Liberty) for consistency
|
||||||
|
obj["ibm_datetime"] = strings.Replace(obj["ibm_datetime"].(string), "+0000", "Z", 1)
|
||||||
|
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
|
// mirrorSystemErrorLogs starts a goroutine to mirror the contents of the MQ system error logs
|
||||||
@@ -82,6 +102,16 @@ func mirrorQueueManagerErrorLogs(ctx context.Context, wg *sync.WaitGroup, name s
|
|||||||
return mirrorLog(ctx, wg, f, fromStart, mf, true)
|
return mirrorLog(ctx, wg, f, fromStart, mf, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mirrorHTPasswdLogs starts a goroutine to mirror the contents of the MQ HTPasswd authorization service's log
|
||||||
|
func mirrorHTPasswdLogs(ctx context.Context, wg *sync.WaitGroup, name string, fromStart bool, mf mirrorFunc) (chan error, error) {
|
||||||
|
return mirrorLog(ctx, wg, "/var/mqm/errors/mqhtpass.json", false, mf, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mirrorWebServerLogs starts a goroutine to mirror the contents of the Liberty web server messages.log
|
||||||
|
func mirrorWebServerLogs(ctx context.Context, wg *sync.WaitGroup, name string, fromStart bool, mf mirrorFunc) (chan error, error) {
|
||||||
|
return mirrorLog(ctx, wg, "/var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log", false, mf, true)
|
||||||
|
}
|
||||||
|
|
||||||
func getDebug() bool {
|
func getDebug() bool {
|
||||||
debug := os.Getenv("DEBUG")
|
debug := os.Getenv("DEBUG")
|
||||||
if debug == "true" || debug == "1" {
|
if debug == "true" || debug == "1" {
|
||||||
@@ -101,14 +131,21 @@ func configureLogger(name string) (mirrorFunc, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return func(msg string, isQMLog bool) bool {
|
return func(msg string, isQMLog bool) bool {
|
||||||
obj, err := processLogMessage(msg)
|
// Check if the message is JSON
|
||||||
if err == nil && isQMLog && filterQMLogMessage(obj) {
|
if len(msg) > 0 && msg[0] == '{' {
|
||||||
return false
|
obj, err := processLogMessage(msg)
|
||||||
}
|
if err == nil && isQMLog && filterQMLogMessage(obj) {
|
||||||
if err != nil {
|
return false
|
||||||
log.Printf("Failed to unmarshall JSON - %v", msg)
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to unmarshall JSON in log message - %v", msg)
|
||||||
|
} else {
|
||||||
|
fmt.Println(msg)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(msg)
|
// The log being mirrored isn't JSON, so wrap it in a simple JSON message
|
||||||
|
// MQ error logs are usually JSON, but this is useful for Liberty logs - usually expect WLP_LOGGING_MESSAGE_FORMAT=JSON to be set when mirroring Liberty logs.
|
||||||
|
fmt.Printf("{\"message\":\"%s\"}\n", msg)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil
|
}, nil
|
||||||
@@ -118,15 +155,22 @@ func configureLogger(name string) (mirrorFunc, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return func(msg string, isQMLog bool) bool {
|
return func(msg string, isQMLog bool) bool {
|
||||||
// Parse the JSON message, and print a simplified version
|
// Check if the message is JSON
|
||||||
obj, err := processLogMessage(msg)
|
if len(msg) > 0 && msg[0] == '{' {
|
||||||
if err == nil && isQMLog && filterQMLogMessage(obj) {
|
// Parse the JSON message, and print a simplified version
|
||||||
return false
|
obj, err := processLogMessage(msg)
|
||||||
}
|
if err == nil && isQMLog && filterQMLogMessage(obj) {
|
||||||
if err != nil {
|
return false
|
||||||
log.Printf("Failed to unmarshall JSON - %v", err)
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to unmarshall JSON in log message - %v", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf(formatBasic(obj))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(formatSimple(obj["ibm_datetime"].(string), obj["message"].(string)))
|
// The log being mirrored isn't JSON, so just print it.
|
||||||
|
// MQ error logs are usually JSON, but this is useful for Liberty logs - usually expect WLP_LOGGING_MESSAGE_FORMAT=JSON to be set when mirroring Liberty logs.
|
||||||
|
fmt.Println(msg)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil
|
}, nil
|
||||||
@@ -154,41 +198,43 @@ func filterQMLogMessage(obj map[string]interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func logDiagnostics() {
|
func logDiagnostics() {
|
||||||
log.Debug("--- Start Diagnostics ---")
|
if getDebug() {
|
||||||
|
log.Debug("--- Start Diagnostics ---")
|
||||||
|
|
||||||
// show the directory ownership/permissions
|
// show the directory ownership/permissions
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ := command.Run("ls", "-l", "/mnt/")
|
out, _, _ := command.Run("ls", "-l", "/mnt/")
|
||||||
log.Debugf("/mnt/:\n%s", out)
|
log.Debugf("/mnt/:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm")
|
out, _, _ = command.Run("ls", "-l", "/mnt/mqm")
|
||||||
log.Debugf("/mnt/mqm:\n%s", out)
|
log.Debugf("/mnt/mqm:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm/data")
|
out, _, _ = command.Run("ls", "-l", "/mnt/mqm/data")
|
||||||
log.Debugf("/mnt/mqm/data:\n%s", out)
|
log.Debugf("/mnt/mqm/data:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-log/log")
|
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-log/log")
|
||||||
log.Debugf("/mnt/mqm-log/log:\n%s", out)
|
log.Debugf("/mnt/mqm-log/log:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-data/qmgrs")
|
out, _, _ = command.Run("ls", "-l", "/mnt/mqm-data/qmgrs")
|
||||||
log.Debugf("/mnt/mqm-data/qmgrs:\n%s", out)
|
log.Debugf("/mnt/mqm-data/qmgrs:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/var/mqm")
|
out, _, _ = command.Run("ls", "-l", "/var/mqm")
|
||||||
log.Debugf("/var/mqm:\n%s", out)
|
log.Debugf("/var/mqm:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/var/mqm/errors")
|
out, _, _ = command.Run("ls", "-l", "/var/mqm/errors")
|
||||||
log.Debugf("/var/mqm/errors:\n%s", out)
|
log.Debugf("/var/mqm/errors:\n%s", out)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
out, _, _ = command.Run("ls", "-l", "/etc/mqm")
|
out, _, _ = command.Run("ls", "-l", "/etc/mqm")
|
||||||
log.Debugf("/etc/mqm:\n%s", out)
|
log.Debugf("/etc/mqm:\n%s", out)
|
||||||
|
|
||||||
// Print out summary of any FDCs
|
// Print out summary of any FDCs
|
||||||
// #nosec G204
|
// #nosec G204
|
||||||
cmd := exec.Command("/opt/mqm/bin/ffstsummary")
|
cmd := exec.Command("/opt/mqm/bin/ffstsummary")
|
||||||
cmd.Dir = "/var/mqm/errors"
|
cmd.Dir = "/var/mqm/errors"
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
outB, _ := cmd.CombinedOutput()
|
outB, _ := cmd.CombinedOutput()
|
||||||
log.Debugf("ffstsummary:\n%s", string(outB))
|
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, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -24,8 +24,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/ha"
|
||||||
"github.com/ibm-messaging/mq-container/internal/metrics"
|
"github.com/ibm-messaging/mq-container/internal/metrics"
|
||||||
"github.com/ibm-messaging/mq-container/internal/mqinimerge"
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||||
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
"github.com/ibm-messaging/mq-container/pkg/containerruntimelogger"
|
||||||
@@ -113,12 +113,29 @@ func doMain() error {
|
|||||||
return err
|
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()
|
err = createDirStructure()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return 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 init flag is set, exit now
|
||||||
if *initFlag {
|
if *initFlag {
|
||||||
return nil
|
return nil
|
||||||
@@ -127,29 +144,55 @@ func doMain() error {
|
|||||||
// Print out versioning information
|
// Print out versioning information
|
||||||
logVersionInfo()
|
logVersionInfo()
|
||||||
|
|
||||||
keylabel, cmsDB, p12Trust, _, err := tls.ConfigureTLSKeystores(keyDir, trustDir, keyStoreDir)
|
keyLabel, defaultCmsKeystore, defaultP12Truststore, err := tls.ConfigureDefaultTLSKeystores()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = configureTLS(keylabel, cmsDB, *devFlag)
|
err = tls.ConfigureTLS(keyLabel, defaultCmsKeystore, *devFlag, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = postInit(name, keylabel, p12Trust)
|
err = postInit(name, keyLabel, defaultP12Truststore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newQM, err := createQueueManager(name)
|
if os.Getenv("MQ_NATIVE_HA") == "true" {
|
||||||
|
err = ha.ConfigureNativeHA(log)
|
||||||
|
if err != nil {
|
||||||
|
logTermination(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enableTraceCrtmqm := os.Getenv("MQ_ENABLE_TRACE_CRTMQM")
|
||||||
|
if enableTraceCrtmqm == "true" || enableTraceCrtmqm == "1" {
|
||||||
|
err = startMQTrace()
|
||||||
|
if err != nil {
|
||||||
|
logTermination(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newQM, err := createQueueManager(name, *devFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if enableTraceCrtmqm == "true" || enableTraceCrtmqm == "1" {
|
||||||
|
err = endMQTrace()
|
||||||
|
if err != nil {
|
||||||
|
logTermination(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
defer func() {
|
defer func() {
|
||||||
log.Debug("Waiting for log mirroring to complete")
|
log.Debug("Waiting for log mirroring to complete")
|
||||||
@@ -171,16 +214,46 @@ func doMain() error {
|
|||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if *devFlag {
|
||||||
|
_, err = mirrorHTPasswdLogs(ctx, &wg, name, newQM, mf)
|
||||||
|
if err != nil {
|
||||||
|
logTermination(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recommended to use this option in conjunction with setting WLP_LOGGING_MESSAGE_FORMAT=JSON
|
||||||
|
mirrorWebLog := os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG")
|
||||||
|
if mirrorWebLog == "true" || mirrorWebLog == "1" {
|
||||||
|
_, err = mirrorWebServerLogs(ctx, &wg, name, newQM, mf)
|
||||||
|
if err != nil {
|
||||||
|
logTermination(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = updateCommandLevel()
|
err = updateCommandLevel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mqinimerge.AddStanzas(name)
|
enableTraceStrmqm := os.Getenv("MQ_ENABLE_TRACE_STRMQM")
|
||||||
if err != nil {
|
if enableTraceStrmqm == "true" || enableTraceStrmqm == "1" {
|
||||||
logTermination(err)
|
err = startMQTrace()
|
||||||
return err
|
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)
|
err = startQueueManager(name)
|
||||||
@@ -188,8 +261,9 @@ func doMain() error {
|
|||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if standby, _ := ready.IsRunningAsStandbyQM(name); !standby {
|
|
||||||
err = configureQueueManager()
|
if enableTraceStrmqm == "true" || enableTraceStrmqm == "1" {
|
||||||
|
err = endMQTrace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logTermination(err)
|
logTermination(err)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -22,23 +22,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// postInit is run after /var/mqm is set up
|
// 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")
|
enableWebServer := os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER")
|
||||||
if enableWebServer == "true" || enableWebServer == "1" {
|
if enableWebServer == "true" || enableWebServer == "1" {
|
||||||
// Configure the web server (if enabled)
|
// Configure the web server (if enabled)
|
||||||
keystore, err := configureWebServer(keylabel, p12Trust)
|
webKeystore, err := configureWebServer(keyLabel, p12Truststore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// If trust-store is empty, set reference to point to the key-store
|
// If trust-store is empty, set reference to point to the keystore
|
||||||
p12TrustStoreRef := "MQWebTrustStore"
|
webTruststoreRef := "MQWebTrustStore"
|
||||||
if len(p12Trust.TrustedCerts) == 0 {
|
if len(p12Truststore.TrustedCerts) == 0 {
|
||||||
p12TrustStoreRef = "MQWebKeyStore"
|
webTruststoreRef = "MQWebKeyStore"
|
||||||
}
|
}
|
||||||
// Start the web server, in the background (if installed)
|
// Start the web server, in the background (if installed)
|
||||||
// WARNING: No error handling or health checking available for the web server
|
// WARNING: No error handling or health checking available for the web server
|
||||||
go func() {
|
go func() {
|
||||||
err = startWebServer(keystore, p12Trust.Password, p12TrustStoreRef)
|
err = startWebServer(webKeystore, p12Truststore.Password, webTruststoreRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error starting web server: %v", err)
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,34 +16,42 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
"github.com/ibm-messaging/mq-container/internal/command"
|
||||||
containerruntime "github.com/ibm-messaging/mq-container/internal/containerruntime"
|
containerruntime "github.com/ibm-messaging/mq-container/internal/containerruntime"
|
||||||
"github.com/ibm-messaging/mq-container/internal/mqscredact"
|
"github.com/ibm-messaging/mq-container/internal/mqscredact"
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/mqversion"
|
||||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||||
)
|
)
|
||||||
|
|
||||||
// createDirStructure creates the default MQ directory structure under /var/mqm
|
// createDirStructure creates the default MQ directory structure under /var/mqm
|
||||||
func createDirStructure() error {
|
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 {
|
if err != nil {
|
||||||
log.Printf("Error creating directory structure: %v\n", string(out))
|
if rc == 10 {
|
||||||
return err
|
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")
|
log.Println("Created directory structure under /var/mqm")
|
||||||
|
logDiagnostics()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createQueueManager creates a queue manager, if it doesn't already exist.
|
// 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
|
// 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)
|
log.Printf("Creating queue manager %v", name)
|
||||||
|
|
||||||
// Run 'dspmqinf' to check if 'mqs.ini' configuration file exists
|
// Run 'dspmqinf' to check if 'mqs.ini' configuration file exists
|
||||||
@@ -66,7 +74,7 @@ func createQueueManager(name string) (bool, error) {
|
|||||||
_, err = os.Stat(filepath.Join(dataDir, "qm.ini"))
|
_, err = os.Stat(filepath.Join(dataDir, "qm.ini"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If 'qm.ini' is not found - run 'crtmqm' to create a new queue manager
|
// 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...)
|
out, rc, err := command.Run("crtmqm", args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error %v creating queue manager: %v", rc, string(out))
|
log.Printf("Error %v creating queue manager: %v", rc, string(out))
|
||||||
@@ -105,9 +113,13 @@ func startQueueManager(name string) error {
|
|||||||
out, rc, err := command.Run("strmqm", "-x", name)
|
out, rc, err := command.Run("strmqm", "-x", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 30=standby queue manager started, which is fine
|
// 30=standby queue manager started, which is fine
|
||||||
|
// 94=native HA replica started, which is fine
|
||||||
if rc == 30 {
|
if rc == 30 {
|
||||||
log.Printf("Started standby queue manager")
|
log.Printf("Started standby queue manager")
|
||||||
return nil
|
return nil
|
||||||
|
} else if rc == 94 {
|
||||||
|
log.Printf("Started replica queue manager")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
log.Printf("Error %v starting queue manager: %v", rc, string(out))
|
log.Printf("Error %v starting queue manager: %v", rc, string(out))
|
||||||
return err
|
return err
|
||||||
@@ -116,74 +128,20 @@ func startQueueManager(name string) error {
|
|||||||
return nil
|
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 {
|
func stopQueueManager(name string) error {
|
||||||
log.Println("Stopping queue manager")
|
log.Println("Stopping queue manager")
|
||||||
|
qmGracePeriod := os.Getenv("MQ_GRACE_PERIOD")
|
||||||
isStandby, err := ready.IsRunningAsStandbyQM(name)
|
isStandby, err := ready.IsRunningAsStandbyQM(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting status for queue manager %v: %v", name, err.Error())
|
log.Printf("Error getting status for queue manager %v: %v", name, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
args := []string{"-w", "-r", name}
|
args := []string{"-w", "-r", "-tp", qmGracePeriod, name}
|
||||||
if os.Getenv("MQ_MULTI_INSTANCE") == "true" {
|
if os.Getenv("MQ_MULTI_INSTANCE") == "true" {
|
||||||
if isStandby {
|
if isStandby {
|
||||||
args = []string{"-x", name}
|
args = []string{"-x", name}
|
||||||
} else {
|
} else {
|
||||||
args = []string{"-s", "-w", "-r", name}
|
args = []string{"-s", "-w", "-r", "-tp", qmGracePeriod, name}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out, rc, err := command.Run("endmqm", args...)
|
out, rc, err := command.Run("endmqm", args...)
|
||||||
@@ -199,6 +157,28 @@ func stopQueueManager(name string) error {
|
|||||||
return nil
|
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 {
|
func formatMQSCOutput(out string) string {
|
||||||
// redact sensitive information
|
// redact sensitive information
|
||||||
out, _ = mqscredact.Redact(out)
|
out, _ = mqscredact.Redact(out)
|
||||||
@@ -227,8 +207,30 @@ func getQueueManagerDataDir(mounts map[string]string, name string) string {
|
|||||||
return dataDir
|
return dataDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCreateQueueManagerArgs(mounts map[string]string, name string) []string {
|
func getCreateQueueManagerArgs(mounts map[string]string, name string, devMode bool) []string {
|
||||||
args := []string{"-q", "-p", "1414"}
|
|
||||||
|
mqversionBase := "9.2.1.0"
|
||||||
|
|
||||||
|
// use "UserExternal" only if we are 9.2.1.0 or above.
|
||||||
|
oaVal := "user"
|
||||||
|
mqVersionCheck, err := mqversion.Compare(mqversionBase)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error comparing MQ versions for oa,rc: %v", mqVersionCheck)
|
||||||
|
}
|
||||||
|
if mqVersionCheck >= 0 {
|
||||||
|
oaVal = "UserExternal"
|
||||||
|
}
|
||||||
|
|
||||||
|
//build args
|
||||||
|
args := []string{"-ii", "/etc/mqm/", "-ic", "/etc/mqm/", "-q", "-p", "1414"}
|
||||||
|
|
||||||
|
if os.Getenv("MQ_NATIVE_HA") == "true" {
|
||||||
|
args = append(args, "-lr", os.Getenv("HOSTNAME"))
|
||||||
|
}
|
||||||
|
if devMode {
|
||||||
|
args = append(args, "-oa", oaVal)
|
||||||
|
}
|
||||||
if _, ok := mounts["/mnt/mqm-log"]; ok {
|
if _, ok := mounts["/mnt/mqm-log"]; ok {
|
||||||
args = append(args, "-ld", "/mnt/mqm-log/log")
|
args = append(args, "-ld", "/mnt/mqm-log/log")
|
||||||
}
|
}
|
||||||
@@ -247,3 +249,48 @@ func getCreateStandbyQueueManagerArgs(name string) []string {
|
|||||||
args = append(args, "-v", fmt.Sprintf("DataPath=/mnt/mqm-data/qmgrs/%v", name))
|
args = append(args, "-v", fmt.Sprintf("DataPath=/mnt/mqm-data/qmgrs/%v", name))
|
||||||
return args
|
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,163 +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"
|
|
||||||
|
|
||||||
if os.Getenv("MQ_DEV") == "true" {
|
|
||||||
err := mqtemplate.ProcessTemplateFile(mqscTemplate, mqsc, map[string]string{}, 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// configureWebKeyStore configures the key stores for the web console
|
|
||||||
func configureWebKeyStore(p12TrustStore tls.KeyStoreData) (string, error) {
|
|
||||||
// TODO find way to supply this
|
|
||||||
// Override the webstore variables to hard coded defaults
|
|
||||||
webKeyStoreName := tls.WebDefaultLabel + ".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
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
"github.com/ibm-messaging/mq-container/internal/command"
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/mqversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -50,7 +51,7 @@ func logImageTag() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func logMQVersion() {
|
func logMQVersion() {
|
||||||
mqVersion, _, err := command.Run("dspmqver", "-b", "-f", "2")
|
mqVersion, err := mqversion.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error Getting MQ version: %v", strings.TrimSuffix(string(mqVersion), "\n"))
|
log.Printf("Error Getting MQ version: %v", strings.TrimSuffix(string(mqVersion), "\n"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -19,19 +19,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"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/copy"
|
||||||
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
||||||
"github.com/ibm-messaging/mq-container/internal/tls"
|
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error {
|
func startWebServer(webKeystore, webkeystorePW, webTruststoreRef string) error {
|
||||||
_, err := os.Stat("/opt/mqm/bin/strmqweb")
|
_, err := os.Stat("/opt/mqm/bin/strmqweb")
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
log.Debug("Skipping web server, because it's not installed")
|
log.Debug("Skipping web server, because it's not installed")
|
||||||
@@ -50,28 +46,10 @@ func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TLS enabled
|
// TLS enabled
|
||||||
if keystore != "" {
|
if webKeystore != "" {
|
||||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+keystore)
|
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTORE="+webKeystore)
|
||||||
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+keystorepw)
|
cmd.Env = append(cmd.Env, "AMQ_WEBKEYSTOREPW="+webkeystorePW)
|
||||||
cmd.Env = append(cmd.Env, "AMQ_WEBTRUSTSTOREREF="+p12TrustStoreRef)
|
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, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
rc := cmd.ProcessState.ExitCode()
|
rc := cmd.ProcessState.ExitCode()
|
||||||
@@ -83,17 +61,32 @@ func startWebServer(keystore, keystorepw, p12TrustStoreRef string) error {
|
|||||||
return nil
|
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{}
|
||||||
requiredEnvVars := []string{
|
_, set := os.LookupEnv("MQ_ZEN_INTERNAL_ENDPOINT")
|
||||||
"MQ_WEB_ADMIN_USERS",
|
if !set {
|
||||||
"MQ_OIDC_CLIENT_ID",
|
// Ensure all required environment variables are set for SSO
|
||||||
"MQ_OIDC_CLIENT_SECRET",
|
requiredEnvVars = []string{
|
||||||
"MQ_OIDC_UNIQUE_USER_IDENTIFIER",
|
"MQ_OIDC_CLIENT_ID",
|
||||||
"MQ_OIDC_AUTHORIZATION_ENDPOINT",
|
"MQ_OIDC_CLIENT_SECRET",
|
||||||
"MQ_OIDC_TOKEN_ENDPOINT",
|
"MQ_OIDC_UNIQUE_USER_IDENTIFIER",
|
||||||
"MQ_OIDC_JWK_ENDPOINT",
|
"MQ_OIDC_AUTHORIZATION_ENDPOINT",
|
||||||
"MQ_OIDC_ISSUER_IDENTIFIER",
|
"MQ_OIDC_TOKEN_ENDPOINT",
|
||||||
|
"MQ_OIDC_JWK_ENDPOINT",
|
||||||
|
"MQ_OIDC_ISSUER_IDENTIFIER",
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ensure all required environment variables are set for Zen SSO
|
||||||
|
requiredEnvVars = []string{
|
||||||
|
"MQ_ZEN_UNIQUE_USER_IDENTIFIER",
|
||||||
|
"MQ_ZEN_INTERNAL_ENDPOINT",
|
||||||
|
"MQ_ZEN_ISSUER_IDENTIFIER",
|
||||||
|
"MQ_ZEN_AUDIENCES",
|
||||||
|
"MQ_ZEN_CONTEXT_NAME",
|
||||||
|
"MQ_ZEN_BASE_URI",
|
||||||
|
"MQ_ZEN_CONTEXT_NAMESPACE",
|
||||||
|
"IAM_URL",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, envVar := range requiredEnvVars {
|
for _, envVar := range requiredEnvVars {
|
||||||
if len(os.Getenv(envVar)) == 0 {
|
if len(os.Getenv(envVar)) == 0 {
|
||||||
@@ -119,50 +112,49 @@ func configureSSO(p12TrustStore tls.KeyStoreData) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configure SSO TLS
|
// Configure SSO TLS
|
||||||
return configureWebKeyStore(p12TrustStore)
|
return tls.ConfigureWebKeystore(p12TrustStore, webKeystore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, error) {
|
func configureWebServer(keyLabel string, p12Truststore tls.KeyStoreData) (string, error) {
|
||||||
var keystore string
|
var webKeystore string
|
||||||
|
|
||||||
// Configure TLS for Web Console first if we have a certificate to use
|
// Configure TLS for Web Console first if we have a certificate to use
|
||||||
err := configureWebTLS(keyLabel)
|
err := tls.ConfigureWebTLS(keyLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return keystore, err
|
return "", err
|
||||||
}
|
}
|
||||||
if keyLabel != "" {
|
if keyLabel != "" {
|
||||||
keystore = keyLabel + ".p12"
|
webKeystore = keyLabel + ".p12"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure Single-Sign-On for the web server (if enabled)
|
// Configure Single-Sign-On for the web server (if enabled)
|
||||||
enableSSO := os.Getenv("MQ_BETA_ENABLE_SSO")
|
enableSSO := os.Getenv("MQ_BETA_ENABLE_SSO")
|
||||||
if enableSSO == "true" || enableSSO == "1" {
|
if enableSSO == "true" || enableSSO == "1" {
|
||||||
keystore, err = configureSSO(p12Trust)
|
webKeystore, err = configureSSO(p12Truststore, webKeystore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return keystore, err
|
return "", err
|
||||||
}
|
}
|
||||||
} else if keyLabel == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") != "" {
|
} else if keyLabel == "" && os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") != "" {
|
||||||
keystore, err = configureWebKeyStore(p12Trust)
|
webKeystore, err = tls.ConfigureWebKeystore(p12Truststore, webKeystore)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = os.Stat("/opt/mqm/bin/strmqweb")
|
_, err = os.Stat("/opt/mqm/bin/strmqweb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return keystore, nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return keystore, err
|
return "", err
|
||||||
}
|
}
|
||||||
const webConfigDir string = "/etc/mqm/web"
|
const webConfigDir string = "/etc/mqm/web"
|
||||||
_, err = os.Stat(webConfigDir)
|
_, err = os.Stat(webConfigDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return keystore, nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return keystore, err
|
return "", err
|
||||||
}
|
|
||||||
uid, gid, err := command.LookupMQM()
|
|
||||||
if err != nil {
|
|
||||||
return keystore, err
|
|
||||||
}
|
}
|
||||||
const prefix string = "/etc/mqm/web"
|
const prefix string = "/etc/mqm/web"
|
||||||
err = filepath.Walk(prefix, func(from string, info os.FileInfo, err error) error {
|
err = filepath.Walk(prefix, func(from string, info os.FileInfo, err error) error {
|
||||||
@@ -200,11 +192,8 @@ func configureWebServer(keyLabel string, p12Trust tls.KeyStoreData) (string, err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = os.Chown(to, uid, gid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return keystore, err
|
|
||||||
|
return webKeystore, err
|
||||||
}
|
}
|
||||||
|
|||||||
6
config.env
Normal file
6
config.env
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
###########################################################################################################################################################
|
||||||
|
|
||||||
|
# MQ_VERSION is the fully qualified MQ version number to build
|
||||||
|
MQ_VERSION ?= 9.2.3.0
|
||||||
|
|
||||||
|
###########################################################################################################################################################
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# © Copyright IBM Corporation 2017, 2018
|
# © Copyright IBM Corporation 2020
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,13 +12,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
[[constraint]]
|
FROM fedora:32
|
||||||
name = "github.com/docker/docker"
|
RUN yum install skopeo -y -qq
|
||||||
version = "=v17.03.2-ce"
|
ENTRYPOINT [ "skopeo" ]
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/docker/go-connections"
|
|
||||||
version = "0.4.0"
|
|
||||||
|
|
||||||
[prune]
|
|
||||||
go-tests = true
|
|
||||||
@@ -9,18 +9,22 @@ You need to have the following tools installed:
|
|||||||
|
|
||||||
If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first.
|
If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first.
|
||||||
|
|
||||||
You will also need a [Red Hat Account](https://access.redhat.com) to be able to access the Red Hat Registry.
|
You will also need a [Red Hat Account](https://access.redhat.com) to be able to access the Red Hat Registry.
|
||||||
|
|
||||||
## Building a production image
|
## Building a production image
|
||||||
|
|
||||||
|
From MQ 9.2.X, the MQ container adds support for MQ Long Term Support (LTS) **production licensed** releases.
|
||||||
|
|
||||||
|
### MQ Continuous Delivery (CD)
|
||||||
|
|
||||||
This procedure works for building the MQ Continuous Delivery release, on `amd64`, `ppc64le` and `s390x` architectures.
|
This procedure works for building the MQ Continuous Delivery release, on `amd64`, `ppc64le` and `s390x` architectures.
|
||||||
|
|
||||||
1. Create a `downloads` directory in the root of this repository
|
1. Create a `downloads` directory in the root of this repository
|
||||||
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `IBM_MQ_9.1.4_LINUX_X86-64.tar.gz`) in the `downloads` directory
|
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `IBM_MQ_9.2.3_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.
|
3. Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
|
||||||
4. Run `make build-advancedserver`
|
4. Run `make build-advancedserver`
|
||||||
|
|
||||||
> **Warning**: Note that MQ offers two different sets of packaging on Linux: one is called "MQ for Linux" and contains RPM files for installing on Red Hat Enterprise Linux and SUSE Linux Enterprise Server; the other is for Ubuntu. The MQ container build uses a Red Hat Universal Base Image, so you need the "MQ for Linux" RPM files.
|
> **Warning**: Note that from MQ 9.2.X CD, 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:
|
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:
|
||||||
|
|
||||||
@@ -28,6 +32,23 @@ If you have an MQ archive file with a different file name, you can specify a par
|
|||||||
MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
|
MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### MQ Long Term Support (LTS)
|
||||||
|
|
||||||
|
This procedure works for building the MQ Long Term Support 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, `9.2.0.1-IBM-MQ-Advanced-Non-Install-LinuxX86.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 `LTS=true make build-advancedserver`
|
||||||
|
|
||||||
|
> **Warning**: Note that from MQ 9.2 LTS, the MQ container build uses a 'No-Install' MQ Package, available under `IBM MQ V9.2 Long Term Support Release components eAssembly, part no. CXXXXXX`
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 LTS=true make build-advancedserver
|
||||||
|
```
|
||||||
|
|
||||||
## Building a developer image
|
## Building a developer image
|
||||||
|
|
||||||
Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
|
Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
|
||||||
@@ -37,4 +58,4 @@ You can use the environment variable `MQ_ARCHIVE_DEV` to specify an alternative
|
|||||||
|
|
||||||
## Installed components
|
## 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_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_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_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
|
## Details of the default configuration
|
||||||
|
|
||||||
The following users are created:
|
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.
|
* 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.
|
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.
|
||||||
@@ -45,6 +43,6 @@ If you choose to accept the security warning, you will be presented with the log
|
|||||||
* **User:** admin
|
* **User:** admin
|
||||||
* **Password:** passw0rd
|
* **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`.
|
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`.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ The resulting Docker image contains the following:
|
|||||||
- `runmqdevserver` - The main process for MQ Advanced for Developers
|
- `runmqdevserver` - The main process for MQ Advanced for Developers
|
||||||
- `chkmqhealthy` - Checks the health of the queue manager. This can be used by (say) a Kubernetes liveness probe.
|
- `chkmqhealthy` - Checks the health of the queue manager. This can be used by (say) a Kubernetes liveness probe.
|
||||||
- `chkmqready` - Checks if the queue manager is ready for work. This can be used by (say) a Kubernetes readiness probe.
|
- `chkmqready` - Checks if the queue manager is ready for work. This can be used by (say) a Kubernetes readiness probe.
|
||||||
|
- `chkmqstarted` - Checks if the queue manager has successfully started. This can be used by (say) a Kubernetes startup probe.
|
||||||
|
|
||||||
## runmqserver
|
## runmqserver
|
||||||
The `runmqserver` command has the following responsibilities:
|
The `runmqserver` command has the following responsibilities:
|
||||||
|
|||||||
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 `mqhtpass.log` is generated under `/var/mqm/errors` directory path of the container. This file will contain all the failed connection authentication requests. Additional information is logged to this file if the environment variable `DEBUG` is set to `true`.
|
||||||
|
|
||||||
|
**Please note**: This log file will be wiped when the queue manager is next started.
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
### User
|
### 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
|
### Capabilities
|
||||||
|
|
||||||
@@ -16,24 +16,5 @@ docker run \
|
|||||||
--env LICENSE=accept \
|
--env LICENSE=accept \
|
||||||
--env MQ_QMGR_NAME=QM1 \
|
--env MQ_QMGR_NAME=QM1 \
|
||||||
--detach \
|
--detach \
|
||||||
mqadvanced-server:9.1.4.0-amd64
|
ibm-mqadvanced-server:9.2.3.0-amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
The MQ Advanced for Developers image does require the "chown", "setuid", "setgid" and "audit_write" capabilities (plus "dac_override" if you're using an image based on Red Hat Enterprise Linux). This is because it uses the "sudo" command to change passwords inside the container. For example, in Docker, you could do the following:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run \
|
|
||||||
--cap-drop=ALL \
|
|
||||||
--cap-add=CHOWN \
|
|
||||||
--cap-add=SETUID \
|
|
||||||
--cap-add=SETGID \
|
|
||||||
--cap-add=AUDIT_WRITE \
|
|
||||||
--env LICENSE=accept \
|
|
||||||
--env MQ_QMGR_NAME=QM1 \
|
|
||||||
--detach \
|
|
||||||
mqadvanced-server-dev:9.1.4.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
|
2. Docker tests, which test a complete Docker image, using the Docker API
|
||||||
|
|
||||||
### Running the Docker tests
|
### 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 devserver
|
||||||
make test-advancedserver
|
make advancedserver
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify the image to use directly by using the `MQ_IMAGE_ADVANCEDSERVER` or `MQ_IMAGE_DEVSERVER` variables, for example:
|
You can specify the image to use directly by using the `MQ_IMAGE_ADVANCEDSERVER` or `MQ_IMAGE_DEVSERVER` variables, for example:
|
||||||
|
|
||||||
```
|
```
|
||||||
MQ_IMAGE_ADVANCEDSERVER=mqadvanced-server:9.1.4.0-amd64 make test-advancedserver
|
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:9.2.3.0-amd64 make test-advancedserver
|
||||||
```
|
```
|
||||||
|
|
||||||
You can pass parameters to `go test` with an environment variable. For example, to run the "TestGoldenPath" test, run the following command::
|
You can pass parameters to `go test` with an environment variable. For example, to run the "TestGoldenPath" test, run the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
TEST_OPTS_DOCKER="-run TestGoldenPath" make test-advancedserver
|
TEST_OPTS_DOCKER="-run TestGoldenPath" make test-advancedserver
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use the same environment variables you specified when [building](./building), for example, the following will try and test an image called `mqadvanced-server:9.1.4.0-amd64`:
|
You can also use the same environment variables you specified when [building](./building), for example, the following will try and test an image called `ibm-mqadvanced-server:9.2.0.0-amd64`:
|
||||||
|
|
||||||
```
|
```
|
||||||
MQ_VERSION=9.1.4.0 make test-advancedserver
|
MQ_VERSION=9.2.0.0 make test-advancedserver
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running the Docker tests with code coverage
|
### 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.
|
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
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -60,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
|
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.
|
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.
|
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
|
```dockerfile
|
||||||
FROM ibmcom/mq
|
FROM ibmcom/mq
|
||||||
USER root
|
USER 1001
|
||||||
RUN useradd alice -G mqm && \
|
|
||||||
echo alice:passw0rd | chpasswd
|
|
||||||
USER mqm
|
|
||||||
COPY 20-config.mqsc /etc/mqm/
|
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:
|
Here is an example corresponding `20-config.mqsc` script, which creates two local queues:
|
||||||
|
|
||||||
```mqsc
|
```mqsc
|
||||||
|
|||||||
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/mqhtpass.so
|
||||||
|
ComponentDataSize=0
|
||||||
|
ServiceComponent:
|
||||||
|
Service=AuthorizationService
|
||||||
|
Name=MQSeries.UNIX.auth.service
|
||||||
|
Module=amqzfu
|
||||||
|
ComponentDataSize=0
|
||||||
|
|
||||||
17
go.mod
Normal file
17
go.mod
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module github.com/ibm-messaging/mq-container
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/genuinetools/amicontained v0.4.0
|
||||||
|
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb // indirect
|
||||||
|
github.com/ibm-messaging/mq-golang v2.0.0+incompatible
|
||||||
|
github.com/prometheus/client_golang v1.7.1
|
||||||
|
github.com/prometheus/client_model v0.2.0
|
||||||
|
github.com/prometheus/common v0.14.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.2.0 // indirect
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
|
||||||
|
software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001
|
||||||
|
)
|
||||||
427
go.sum
Normal file
427
go.sum
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
|
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||||
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||||
|
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||||
|
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||||
|
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/genuinetools/amicontained v0.4.0 h1:J70LMWTebQqQJQaQx9uAW82A6QQqe5ux9GMFgo3NAGY=
|
||||||
|
github.com/genuinetools/amicontained v0.4.0/go.mod h1:PAMZkg9CcUTa6gNyULQ6tOMTMEb2HTKJufvKeFqDw+o=
|
||||||
|
github.com/genuinetools/amicontained v0.4.3 h1:cqq9XiAHfWWY3dk8VU8bSJFu9yh8Il5coEdeTAPq72o=
|
||||||
|
github.com/genuinetools/amicontained v0.4.3/go.mod h1:PAMZkg9CcUTa6gNyULQ6tOMTMEb2HTKJufvKeFqDw+o=
|
||||||
|
github.com/genuinetools/amicontained v0.4.9 h1:/LvLdgD7iO3IPk7neqfcwB7ufoH7tG77u1pERXBIj7w=
|
||||||
|
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb h1:9MQ4N7zyYTtdjLGqE5McDbgjIjqR5TAPc6lytEOdndc=
|
||||||
|
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb/go.mod h1:XTcrCYlXPxnxL2UpnwuRn7tcaTn9HAhxFoFJucootk8=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||||
|
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||||
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||||
|
github.com/ibm-messaging/mq-golang v1.0.0 h1:NZHBQlJzAuNsVv09sooYgxBWPvRUX4L6wZIuOSumiKE=
|
||||||
|
github.com/ibm-messaging/mq-golang v2.0.0+incompatible h1:xAufRPYSzoRGaME2+x7LcW5+uvy/G3xL/3Sn3u+G/lY=
|
||||||
|
github.com/ibm-messaging/mq-golang v2.0.0+incompatible/go.mod h1:qjsZDb7m1oKnbPeDma2JVJTKgyCA91I4bcJ1qHY+gcA=
|
||||||
|
github.com/ibm-messaging/mq-golang v3.0.0+incompatible h1:Yc3c8emAyveT54uNDRMkgvS+EBAHeLNWHkc3hk5x+IY=
|
||||||
|
github.com/ibm-messaging/mq-golang v3.0.0+incompatible/go.mod h1:qjsZDb7m1oKnbPeDma2JVJTKgyCA91I4bcJ1qHY+gcA=
|
||||||
|
github.com/ibm-messaging/mq-golang/v5 v5.0.0-alpha h1:Bw2c+k+o9VTMXpiVBmX6PKOm/vPuihx6dO2knPAhkKc=
|
||||||
|
github.com/ibm-messaging/mq-golang/v5 v5.0.0-alpha/go.mod h1:ywCwmYbJOU/E0rl+z4GiNoxVMty68O+LVO39a1VMXrE=
|
||||||
|
github.com/ibm-messaging/mq-golang/v5 v5.1.2 h1:u0e1Vce2TNqJpH088vF77rDMsnMRWnGaOIlxZo4DMZc=
|
||||||
|
github.com/ibm-messaging/mq-golang/v5 v5.1.2/go.mod h1:ywCwmYbJOU/E0rl+z4GiNoxVMty68O+LVO39a1VMXrE=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
|
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||||
|
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||||
|
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||||
|
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||||
|
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
|
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||||
|
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||||
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
|
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
|
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
|
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||||
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
|
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||||
|
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||||
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
|
github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
|
||||||
|
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||||
|
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
|
||||||
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||||
|
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
|
||||||
|
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
|
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||||
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||||
|
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||||
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
|
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
|
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||||
|
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
|
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae h1:duLSQW+DZ5MsXKX7kc4rXlq6/mmxz4G6ewJuBPlhRe0=
|
||||||
|
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001 h1:AVd6O+azYjVQYW1l55IqkbL8/JxjrLtO6q4FCmV8N5c=
|
||||||
|
software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001/go.mod h1:/xvNRWUqm0+/ZMiF4EX00vrSCMsE4/NHb+Pt3freEeQ=
|
||||||
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
18
ha/native-ha.ini.tpl
Normal file
18
ha/native-ha.ini.tpl
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
NativeHALocalInstance:
|
||||||
|
Name={{ .Name }}
|
||||||
|
{{ if .CertificateLabel }}
|
||||||
|
CertificateLabel={{ .CertificateLabel }}
|
||||||
|
KeyRepository={{ .KeyRepository }}
|
||||||
|
{{ if .CipherSpec }}
|
||||||
|
CipherSpec={{ .CipherSpec }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
NativeHAInstance:
|
||||||
|
Name={{ .NativeHAInstance0_Name }}
|
||||||
|
ReplicationAddress={{ .NativeHAInstance0_ReplicationAddress }}
|
||||||
|
NativeHAInstance:
|
||||||
|
Name={{ .NativeHAInstance1_Name }}
|
||||||
|
ReplicationAddress={{ .NativeHAInstance1_ReplicationAddress }}
|
||||||
|
NativeHAInstance:
|
||||||
|
Name={{ .NativeHAInstance2_Name }}
|
||||||
|
ReplicationAddress={{ .NativeHAInstance2_ReplicationAddress }}
|
||||||
@@ -40,8 +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.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(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(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
|
* Developer authority records
|
||||||
SET AUTHREC GROUP('mqclient') OBJTYPE(QMGR) AUTHADD(CONNECT,INQ)
|
SET AUTHREC PRINCIPAL('app') OBJTYPE(QMGR) AUTHADD(CONNECT,INQ)
|
||||||
SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(QUEUE) AUTHADD(BROWSE,GET,INQ,PUT)
|
SET AUTHREC PROFILE('DEV.**') PRINCIPAL('app') OBJTYPE(QUEUE) AUTHADD(BROWSE,GET,INQ,PUT)
|
||||||
SET AUTHREC PROFILE('DEV.**') GROUP('mqclient') OBJTYPE(TOPIC) AUTHADD(PUB,SUB)
|
SET AUTHREC PROFILE('DEV.**') PRINCIPAL('app') OBJTYPE(TOPIC) AUTHADD(PUB,SUB)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# -*- mode: sh -*-
|
# -*- mode: sh -*-
|
||||||
# © Copyright IBM Corporation 2019
|
# © Copyright IBM Corporation 2019, 2021
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -25,17 +25,17 @@ test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
|
|||||||
if ($UBUNTU); then
|
if ($UBUNTU); then
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y --no-install-recommends sudo
|
apt-get install -y --no-install-recommends libaprutil1
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ($YUM); then
|
if ($YUM); then
|
||||||
yum -y install sudo
|
yum -y install apr-util-openssl
|
||||||
yum -y clean all
|
yum -y clean all
|
||||||
rm -rf /var/cache/yum/*
|
rm -rf /var/cache/yum/*
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ($MICRODNF); then
|
if ($MICRODNF); then
|
||||||
microdnf install sudo
|
microdnf --disableplugin=subscription-manager install apr-util-openssl
|
||||||
microdnf clean all
|
microdnf --disableplugin=subscription-manager clean all
|
||||||
fi
|
fi
|
||||||
@@ -36,5 +36,8 @@
|
|||||||
</basicRegistry>
|
</basicRegistry>
|
||||||
<variable name="httpHost" value="*"/>
|
<variable name="httpHost" value="*"/>
|
||||||
<variable name="managementMode" value="externallyprovisioned"/>
|
<variable name="managementMode" value="externallyprovisioned"/>
|
||||||
|
<variable name="mqConsoleEnableUnsafeInline" value="true"/>
|
||||||
|
<jndiEntry jndiName="mqConsoleDefaultCCDTHostname" value="${env.MQ_CONSOLE_DEFAULT_CCDT_HOSTNAME}"/>
|
||||||
|
<jndiEntry jndiName="mqConsoleDefaultCCDTPort" value="${env.MQ_CONSOLE_DEFAULT_CCDT_PORT}"/>
|
||||||
<include location="tls.xml"/>
|
<include location="tls.xml"/>
|
||||||
</server>
|
</server>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# -*- mode: sh -*-
|
# -*- mode: sh -*-
|
||||||
# © Copyright IBM Corporation 2015, 2019
|
# © Copyright IBM Corporation 2015, 2021
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -63,10 +63,10 @@ if ($UBUNTU); then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ($RPM); then
|
if ($RPM); then
|
||||||
EXTRA_RPMS="bash bc ca-certificates file findutils gawk glibc-common grep passwd procps-ng sed shadow-utils tar util-linux which"
|
EXTRA_RPMS="bash bc ca-certificates 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
|
# Install additional packages required by MQ, this install process and the runtime scripts
|
||||||
$YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS}
|
$YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS}
|
||||||
$MICRODNF && microdnf install ${EXTRA_RPMS}
|
$MICRODNF && microdnf --disableplugin=subscription-manager install ${EXTRA_RPMS}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Apply any bug fixes not included in base Ubuntu or MQ image.
|
# Apply any bug fixes not included in base Ubuntu or MQ image.
|
||||||
@@ -78,4 +78,4 @@ $UBUNTU && apt-get install -y libapparmor1 libsystemd0 systemd systemd-sysv libu
|
|||||||
$UBUNTU && rm -rf /var/lib/apt/lists/*
|
$UBUNTU && rm -rf /var/lib/apt/lists/*
|
||||||
$YUM && yum -y clean all
|
$YUM && yum -y clean all
|
||||||
$YUM && rm -rf /var/cache/yum/*
|
$YUM && rm -rf /var/cache/yum/*
|
||||||
$MICRODNF && microdnf clean all
|
$MICRODNF && microdnf --disableplugin=subscription-manager clean all
|
||||||
|
|||||||
101
install-mq.sh
101
install-mq.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# -*- mode: sh -*-
|
# -*- mode: sh -*-
|
||||||
# © Copyright IBM Corporation 2015, 2019
|
# © Copyright IBM Corporation 2015, 2020
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -18,74 +18,70 @@
|
|||||||
# Fail on any non-zero return code
|
# Fail on any non-zero return code
|
||||||
set -ex
|
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/rpm && RPM=true || RPM=false
|
||||||
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
|
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
|
||||||
|
|
||||||
# Download and extract the MQ installation files
|
# Only install the SDK package as part of the build stage
|
||||||
DIR_EXTRACT=/tmp/mq
|
INSTALL_SDK=${INSTALL_SDK:-0}
|
||||||
mkdir -p ${DIR_EXTRACT}
|
|
||||||
cd ${DIR_EXTRACT}
|
# Download and extract the MQ unzippable server
|
||||||
|
DIR_TMP=/tmp/mq
|
||||||
|
mkdir -p ${DIR_TMP}
|
||||||
|
cd ${DIR_TMP}
|
||||||
curl -LO $MQ_URL
|
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
|
tar -xzf ./*.tar.gz
|
||||||
groupadd --system --gid ${mqm_uid} mqm
|
rm -f ./*.tar.gz
|
||||||
useradd --system --uid ${mqm_uid} --gid mqm --groups 0 mqm
|
ls -la ${DIR_TMP}
|
||||||
|
|
||||||
# Find directory containing .deb files
|
# Generate MQ package in INSTALLATION_DIR
|
||||||
$UBUNTU && DIR_DEB=$(find ${DIR_EXTRACT} -name "*.deb" -printf "%h\n" | sort -u | head -1)
|
export genmqpkg_inc32=0
|
||||||
$RPM && DIR_RPM=$(find ${DIR_EXTRACT} -name "*.rpm" -printf "%h\n" | sort -u | head -1)
|
export genmqpkg_incadm=1
|
||||||
# Find location of mqlicense.sh
|
export genmqpkg_incamqp=0
|
||||||
MQLICENSE=$(find ${DIR_EXTRACT} -name "mqlicense.sh")
|
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
|
# Accept the MQ license
|
||||||
${MQLICENSE} -text_only -accept
|
${INSTALLATION_DIR}/bin/mqlicense -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}
|
|
||||||
|
|
||||||
# Optional: Update the command prompt with the MQ version
|
# Optional: Update the command prompt with the MQ version
|
||||||
$UBUNTU && echo "mq:$(dspmqver -b -f 2)" > /etc/debian_chroot
|
$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
|
# 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 2775 --owner 1001 --group root /mnt
|
||||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm
|
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm
|
||||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm/data
|
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm/data
|
||||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-log
|
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-log
|
||||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-log/log
|
install --directory --mode 2775 --owner 1001 --group root /mnt/mqm-log/log
|
||||||
install --directory --mode 0775 --owner mqm --group root /mnt/mqm-data
|
install --directory --mode 2775 --owner 1001 --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/mqm-data/qmgrs
|
||||||
|
|
||||||
# Create the directory for MQ configuration files
|
# 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
|
# 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
|
# Create a symlink for /var/mqm -> /mnt/mqm/data
|
||||||
ln -s /mnt/mqm/data /var/mqm
|
ln -s /mnt/mqm/data /var/mqm
|
||||||
@@ -110,4 +106,3 @@ sed -i 's/v7.0/v8.0/g' /opt/mqm/licenses/non_ibm_license.txt
|
|||||||
# Copy MQ Licenses into the correct location
|
# Copy MQ Licenses into the correct location
|
||||||
mkdir -p /licenses
|
mkdir -p /licenses
|
||||||
cp /opt/mqm/licenses/*.txt /licenses/
|
cp /opt/mqm/licenses/*.txt /licenses/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2017, 2018
|
© Copyright IBM Corporation 2017, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -20,9 +20,6 @@ package command
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Run runs an OS command. On Linux it waits for the command to
|
// Run runs an OS command. On Linux it waits for the command to
|
||||||
@@ -40,33 +37,3 @@ func Run(name string, arg ...string) (string, int, error) {
|
|||||||
}
|
}
|
||||||
return string(out), rc, nil
|
return string(out), rc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunAsMQM runs the specified command as the mqm user
|
|
||||||
func RunAsMQM(name string, arg ...string) (string, int, error) {
|
|
||||||
// #nosec G204
|
|
||||||
cmd := exec.Command(name, arg...)
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
||||||
uid, gid, err := LookupMQM()
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
|
||||||
return Run(name, arg...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|||||||
68
internal/ha/ha.go
Normal file
68
internal/ha/ha.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2020, 2021
|
||||||
|
|
||||||
|
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 ha contains code for high availability
|
||||||
|
package ha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/tls"
|
||||||
|
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConfigureNativeHA configures native high availability
|
||||||
|
func ConfigureNativeHA(log *logger.Logger) error {
|
||||||
|
|
||||||
|
file := "/etc/mqm/native-ha.ini"
|
||||||
|
templateFile := file + ".tpl"
|
||||||
|
|
||||||
|
templateMap := map[string]string{}
|
||||||
|
templateMap["Name"] = os.Getenv("HOSTNAME")
|
||||||
|
templateMap["NativeHAInstance0_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_0_NAME")
|
||||||
|
templateMap["NativeHAInstance1_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_1_NAME")
|
||||||
|
templateMap["NativeHAInstance2_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_NAME")
|
||||||
|
templateMap["NativeHAInstance0_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS")
|
||||||
|
templateMap["NativeHAInstance1_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS")
|
||||||
|
templateMap["NativeHAInstance2_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS")
|
||||||
|
|
||||||
|
if os.Getenv("MQ_NATIVE_HA_TLS") == "true" {
|
||||||
|
keyLabel, _, _, err := tls.ConfigureHATLSKeystore()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
templateMap["CertificateLabel"] = keyLabel
|
||||||
|
|
||||||
|
keyRepository, ok := os.LookupEnv("MQ_NATIVE_HA_KEY_REPOSITORY")
|
||||||
|
if !ok {
|
||||||
|
keyRepository = "/run/runmqserver/ha/tls/key"
|
||||||
|
}
|
||||||
|
templateMap["KeyRepository"] = keyRepository
|
||||||
|
|
||||||
|
cipherSpec, ok := os.LookupEnv("MQ_NATIVE_HA_CIPHERSPEC")
|
||||||
|
if ok {
|
||||||
|
templateMap["CipherSpec"] = cipherSpec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mqtemplate.ProcessTemplateFile(templateFile, file, templateMap, log)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
112
internal/htpasswd/htpasswd.go
Normal file
112
internal/htpasswd/htpasswd.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2020, 2021
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -105,14 +105,6 @@ func (ks *KeyStore) Create() error {
|
|||||||
return fmt.Errorf("error running \"%v -keydb -create\": %v %s", ks.command, err, out)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,14 +122,6 @@ func (ks *KeyStore) CreateStash() error {
|
|||||||
}
|
}
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/ready"
|
"github.com/ibm-messaging/mq-container/internal/ready"
|
||||||
|
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -83,7 +84,7 @@ func startMetricsGathering(qmName string, log *logger.Logger) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup HTTP server to handle requests from Prometheus
|
// Setup HTTP server to handle requests from Prometheus
|
||||||
http.Handle("/metrics", prometheus.Handler())
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
// #nosec G104
|
// #nosec G104
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#*******************************************************************#
|
|
||||||
#* Module Name: mqat.ini *#
|
|
||||||
#* Type : IBM MQ queue manager configuration file *#
|
|
||||||
# Function : Define the configuration of application activity *#
|
|
||||||
#* trace for a single queue manager. *#
|
|
||||||
#*******************************************************************#
|
|
||||||
|
|
||||||
# Global settings stanza, default values
|
|
||||||
AllActivityTrace:
|
|
||||||
ActivityInterval=1
|
|
||||||
ActivityCount=100
|
|
||||||
TraceLevel=MEDIUM
|
|
||||||
TraceMessageData=0
|
|
||||||
StopOnGetTraceMsg=ON
|
|
||||||
SubscriptionDelivery=BATCHED
|
|
||||||
|
|
||||||
# Prevent the sample activity trace program from generating data
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsact*
|
|
||||||
Trace=OFF
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
© Copyright IBM Corporation 2018, 2019
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package mqinimerge merges user-supplied INI files into qm.ini and mqat.ini
|
|
||||||
package mqinimerge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/pkg/mqini"
|
|
||||||
)
|
|
||||||
|
|
||||||
var qmgrDir string
|
|
||||||
|
|
||||||
var stanzasQMINI []string
|
|
||||||
var stanzasMQATINI []string
|
|
||||||
|
|
||||||
// AddStanzas reads supplied MQ INI configuration files and updates the stanzas
|
|
||||||
// in the queue manager's INI configuration files.
|
|
||||||
func AddStanzas(qmname string) error {
|
|
||||||
// Find the qmgr directory.
|
|
||||||
qm, err := mqini.GetQueueManager(qmname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
qmgrDir = mqini.GetDataDirectory(qm)
|
|
||||||
// Find the users ini configuration file
|
|
||||||
files, err := getIniFileList()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(files) > 1 {
|
|
||||||
msg := fmt.Sprintf("[ %v ]", files)
|
|
||||||
return errors.New("Only a single INI file can be provided. Following INI files were found:" + msg)
|
|
||||||
}
|
|
||||||
if len(files) == 0 {
|
|
||||||
// No INI file update required.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//read user supplied config file.
|
|
||||||
iniFileBytes, err := ioutil.ReadFile(files[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
if len(userconfig) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare a list of all supported stanzas
|
|
||||||
PopulateAllAvailableStanzas()
|
|
||||||
|
|
||||||
// Update the qmgr ini file with user config.
|
|
||||||
qminiConfiglist, qmatConfiglist, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writeConfigStanzas(qminiConfiglist, qmatConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PopulateAllAvailableStanzas initializes the INI stanzas prescribed by MQ specification.
|
|
||||||
func PopulateAllAvailableStanzas() {
|
|
||||||
stanzasQMINI = []string{"ExitPath",
|
|
||||||
"Log",
|
|
||||||
"Service",
|
|
||||||
"ServiceComponent",
|
|
||||||
"Channels",
|
|
||||||
"TCP",
|
|
||||||
"ApiExitLocal",
|
|
||||||
"AccessMode",
|
|
||||||
"RestrictedMode",
|
|
||||||
"XAResourceManager",
|
|
||||||
"DefaultBindType",
|
|
||||||
"SSL",
|
|
||||||
"DiagnosticMessages",
|
|
||||||
"Filesystem",
|
|
||||||
"Security",
|
|
||||||
"TuningParameters",
|
|
||||||
"ExitPropertiesLocal",
|
|
||||||
"LU62",
|
|
||||||
"NETBIOS"}
|
|
||||||
|
|
||||||
stanzasMQATINI = []string{"AllActivityTrace", "ApplicationTrace"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIniFileList checks for the user supplied INI file in `/etc/mqm` directory.
|
|
||||||
func getIniFileList() ([]string, error) {
|
|
||||||
fileList := []string{}
|
|
||||||
err := filepath.Walk("/etc/mqm", func(path string, f os.FileInfo, err error) error {
|
|
||||||
if strings.HasSuffix(path, ".ini") {
|
|
||||||
fileList = append(fileList, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return fileList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareConfigStanzasToWrite Reads through the user supplied INI config file and prepares list of
|
|
||||||
// updates to be written into corresponding mq ini files (qm.ini and/or mqat.ini files)
|
|
||||||
func PrepareConfigStanzasToWrite(userconfig string) ([]string, []string, error) {
|
|
||||||
var qminiConfigStr string
|
|
||||||
var mqatiniConfigStr string
|
|
||||||
|
|
||||||
//read the initial version.
|
|
||||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
|
||||||
iniFileBytes, err := ioutil.ReadFile(filepath.Join(qmgrDir, "qm.ini"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
qminiConfigStr = string(iniFileBytes)
|
|
||||||
qminiConfiglist := strings.Split(qminiConfigStr, "\n")
|
|
||||||
|
|
||||||
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
|
|
||||||
iniFileBytes, err = ioutil.ReadFile(filepath.Join(qmgrDir, "mqat.ini"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
mqatiniConfigStr = string(iniFileBytes)
|
|
||||||
qmatConfiglist := strings.Split(mqatiniConfigStr, "\n")
|
|
||||||
|
|
||||||
stanzaListMerge := make(map[string]strings.Builder)
|
|
||||||
stanzaListAppend := make(map[string]strings.Builder)
|
|
||||||
var sbAppend strings.Builder
|
|
||||||
var sbMerger strings.Builder
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(strings.NewReader(userconfig))
|
|
||||||
scanner.Split(bufio.ScanLines)
|
|
||||||
consumetoAppend := false
|
|
||||||
consumeToMerge := false
|
|
||||||
var stanza string
|
|
||||||
|
|
||||||
// Read through the user file and prepare what we want.
|
|
||||||
for scanner.Scan() {
|
|
||||||
//if this is comment or an empty line, ignore it.
|
|
||||||
if strings.HasPrefix(scanner.Text(), "#") || len(strings.TrimSpace(scanner.Text())) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//thumb rule - all stanzas have ":".
|
|
||||||
if strings.Contains(scanner.Text(), ":") {
|
|
||||||
stanza = strings.TrimSpace(scanner.Text())
|
|
||||||
consumetoAppend = false
|
|
||||||
consumeToMerge = false
|
|
||||||
|
|
||||||
// Check if this stanza exists in the qm.ini/mqat.ini files
|
|
||||||
if strings.Contains(qminiConfigStr, stanza) ||
|
|
||||||
(strings.Contains(mqatiniConfigStr, stanza) && !(strings.Contains(stanza, "ApplicationTrace"))) {
|
|
||||||
consumeToMerge = true
|
|
||||||
sbMerger = strings.Builder{}
|
|
||||||
|
|
||||||
stanzaListMerge[stanza] = sbMerger
|
|
||||||
} else {
|
|
||||||
consumetoAppend = true
|
|
||||||
sbAppend = strings.Builder{}
|
|
||||||
stanzaListAppend[stanza] = sbAppend
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if consumetoAppend {
|
|
||||||
sb := stanzaListAppend[stanza]
|
|
||||||
_, err := sb.WriteString(scanner.Text() + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
stanzaListAppend[stanza] = sb
|
|
||||||
}
|
|
||||||
if consumeToMerge {
|
|
||||||
sb := stanzaListMerge[stanza]
|
|
||||||
_, err := sb.WriteString(scanner.Text() + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
stanzaListMerge[stanza] = sb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do merge.
|
|
||||||
if len(stanzaListMerge) > 0 {
|
|
||||||
for key := range stanzaListMerge {
|
|
||||||
toWrite, filename := ValidateStanzaToWrite(key)
|
|
||||||
if toWrite {
|
|
||||||
attrList := stanzaListMerge[key]
|
|
||||||
switch filename {
|
|
||||||
case "qm.ini":
|
|
||||||
qminiConfiglist, err = prepareStanzasToMerge(key, attrList, qminiConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
case "mqat.ini":
|
|
||||||
qmatConfiglist, err = prepareStanzasToMerge(key, attrList, qmatConfiglist)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do append.
|
|
||||||
if len(stanzaListAppend) > 0 {
|
|
||||||
for key := range stanzaListAppend {
|
|
||||||
attrList := stanzaListAppend[key]
|
|
||||||
if strings.Contains(strings.Join(stanzasMQATINI, ", "), strings.TrimSuffix(strings.TrimSpace(key), ":")) {
|
|
||||||
qmatConfiglist = prepareStanzasToAppend(key, attrList, qmatConfiglist)
|
|
||||||
} else {
|
|
||||||
qminiConfiglist = prepareStanzasToAppend(key, attrList, qminiConfiglist)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return qminiConfiglist, qmatConfiglist, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateStanzaToWrite validates stanza to be written and the file it belongs to.
|
|
||||||
func ValidateStanzaToWrite(stanza string) (bool, string) {
|
|
||||||
stanza = strings.TrimSuffix(strings.TrimSpace(stanza), ":")
|
|
||||||
if strings.Contains(strings.Join(stanzasQMINI, ", "), stanza) {
|
|
||||||
return true, "qm.ini"
|
|
||||||
} else if strings.Contains(strings.Join(stanzasMQATINI, ", "), stanza) {
|
|
||||||
return true, "mqat.ini"
|
|
||||||
} else {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepareStanzasToAppend Prepares list of stanzas that are to be appended into qm ini files(qm.ini/mqat.ini)
|
|
||||||
func prepareStanzasToAppend(key string, attrList strings.Builder, iniConfigList []string) []string {
|
|
||||||
newVal := key + "\n" + attrList.String()
|
|
||||||
list := strings.Split(newVal, "\n")
|
|
||||||
iniConfigList = append(iniConfigList, list...)
|
|
||||||
return iniConfigList
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepareStanzasToMerge Prepares list of stanzas that are to be updated into qm ini files(qm.ini/mqat.ini)
|
|
||||||
// These stanzas are already present in mq ini files and their values have to be updated with user supplied ini.
|
|
||||||
func prepareStanzasToMerge(key string, attrList strings.Builder, iniConfigList []string) ([]string, error) {
|
|
||||||
|
|
||||||
pos := -1
|
|
||||||
//find the index of current stanza in qm's ini file.
|
|
||||||
for i := 0; i < len(iniConfigList); i++ {
|
|
||||||
if strings.Contains(iniConfigList[i], key) {
|
|
||||||
pos = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var appList strings.Builder
|
|
||||||
lineScanner := bufio.NewScanner(strings.NewReader(attrList.String()))
|
|
||||||
lineScanner.Split(bufio.ScanLines)
|
|
||||||
|
|
||||||
//Now go through the array and merge the values.
|
|
||||||
for lineScanner.Scan() {
|
|
||||||
attrLine := lineScanner.Text()
|
|
||||||
keyvalue := strings.Split(attrLine, "=")
|
|
||||||
merged := false
|
|
||||||
for i := pos + 1; i < len(iniConfigList); i++ {
|
|
||||||
if strings.HasPrefix(iniConfigList[i], "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.Contains(iniConfigList[i], ":") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if strings.Contains(iniConfigList[i], keyvalue[0]) {
|
|
||||||
iniConfigList[i] = attrLine
|
|
||||||
merged = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If this is not merged, then its a new parameter in existing stanza.
|
|
||||||
if !merged && len(strings.TrimSpace(attrLine)) > 0 {
|
|
||||||
_, err := appList.WriteString(attrLine)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
merged = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(appList.String()) > 0 {
|
|
||||||
temp := make([]string, pos+1)
|
|
||||||
for i := 0; i < pos+1; i++ {
|
|
||||||
temp[i] = iniConfigList[i]
|
|
||||||
}
|
|
||||||
list := strings.Split(appList.String(), "\n")
|
|
||||||
temp = append(temp, list...)
|
|
||||||
temp1 := iniConfigList[pos+1:]
|
|
||||||
iniConfigList = append(temp, temp1...)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return iniConfigList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeFileIfChanged writes the specified data to the specified file path
|
|
||||||
// (just like ioutil.WriteFile), but first checks if this is needed
|
|
||||||
func writeFileIfChanged(path string, data []byte, perm os.FileMode) error {
|
|
||||||
// #nosec G304 - internal utility using file name derived from dspmqinf
|
|
||||||
current, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Only write the new file if the it's different from the current file
|
|
||||||
if !bytes.Equal(current, data) {
|
|
||||||
err = ioutil.WriteFile(path, data, perm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeConfigStanzas writes the INI file updates into corresponding MQ INI files.
|
|
||||||
func writeConfigStanzas(qmConfig []string, atConfig []string) error {
|
|
||||||
err := writeFileIfChanged(filepath.Join(qmgrDir, "qm.ini"), []byte(strings.Join(qmConfig, "\n")), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = writeFileIfChanged(filepath.Join(qmgrDir, "mqat.ini"), []byte(strings.Join(atConfig, "\n")), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
© Copyright IBM Corporation 2018, 2019
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
package mqinimerge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIniFileStanzas(t *testing.T) {
|
|
||||||
PopulateAllAvailableStanzas()
|
|
||||||
|
|
||||||
checkReturns("ApiExitLocal", true, true, t)
|
|
||||||
checkReturns("Channels", true, true, t)
|
|
||||||
checkReturns("TCP", true, true, t)
|
|
||||||
checkReturns("ServiceComponent", true, true, t)
|
|
||||||
checkReturns("Service", true, true, t)
|
|
||||||
checkReturns("AccessMode", true, true, t)
|
|
||||||
checkReturns("RestrictedMode", true, true, t)
|
|
||||||
checkReturns("XAResourceManager", true, true, t)
|
|
||||||
checkReturns("SSL", true, true, t)
|
|
||||||
checkReturns("Security", true, true, t)
|
|
||||||
checkReturns("TuningParameters", true, true, t)
|
|
||||||
checkReturns("ABC", false, false, t)
|
|
||||||
checkReturns("#1234ABD", true, false, t)
|
|
||||||
checkReturns("AllActivityTrace", false, true, t)
|
|
||||||
checkReturns("ApplicationTrace", false, true, t)
|
|
||||||
checkReturns("xyz123abvc", false, false, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile1Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Unexpected stanza file update: mqat.ini[%s]\n", atConfig)
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we want this line to be present exactly one.
|
|
||||||
for _, item := range qmConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "mylib") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile2Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test2qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we want this line to be present exactly one.
|
|
||||||
for _, item := range atConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "amqsget") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=amqsget, Config:%s\n", strings.Join(atConfig, "\n"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile3Update(t *testing.T) {
|
|
||||||
i := 0
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test3qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Unexpected stanza file update: qm.ini[%s]\n", atConfig)
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
qmConfigStr := strings.Join(qmConfig, "\n")
|
|
||||||
atConfigStr := strings.Join(atConfig, "\n")
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(strings.NewReader(userconfig))
|
|
||||||
scanner.Split(bufio.ScanLines)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
i++
|
|
||||||
//first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file.
|
|
||||||
if i < 20 {
|
|
||||||
if !strings.Contains(qmConfigStr, strings.TrimSpace(line)) {
|
|
||||||
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfigStr)
|
|
||||||
}
|
|
||||||
} else if i > 20 {
|
|
||||||
if !strings.Contains(atConfigStr, line) {
|
|
||||||
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, atConfigStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIniFile4Update(t *testing.T) {
|
|
||||||
iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
//First merge
|
|
||||||
userconfig := string(iniFileBytes)
|
|
||||||
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
//second merge.
|
|
||||||
qmConfig, atConfig, err = PrepareConfigStanzasToWrite(userconfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error: [%s]\n", err.Error())
|
|
||||||
}
|
|
||||||
if len(atConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: mqat.ini\n")
|
|
||||||
}
|
|
||||||
if len(qmConfig) == 0 {
|
|
||||||
t.Errorf("Expected stanza file not found: qm.ini\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
//we just did a double merge, however we want this line to be present exactly one.
|
|
||||||
for _, item := range qmConfig {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if strings.Contains(item, "mylib") {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if count != 1 {
|
|
||||||
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) {
|
|
||||||
exists, filename := ValidateStanzaToWrite(stanza)
|
|
||||||
if exists != shouldexist {
|
|
||||||
t.Errorf("Stanza should exist %t but found was %t", shouldexist, exists)
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldexist {
|
|
||||||
if isqmini {
|
|
||||||
if filename != "qm.ini" {
|
|
||||||
t.Errorf("Expected filename:qm.ini for stanza:%s. But got %s", stanza, filename)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if filename != "mqat.ini" {
|
|
||||||
t.Errorf("Expected filename:mqat.ini for stanza:%s. But got %s", stanza, filename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var writeFileIfChangedTests = []struct {
|
|
||||||
before []byte
|
|
||||||
after []byte
|
|
||||||
same bool
|
|
||||||
}{
|
|
||||||
{[]byte("ABC€"), []byte("ABC€"), true},
|
|
||||||
{[]byte("ABC€"), []byte("ABC$"), false},
|
|
||||||
{[]byte("ABC€"), []byte("BBC€"), false},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteFileIfChanged(t *testing.T) {
|
|
||||||
tmpFile := filepath.Join(os.TempDir(), t.Name())
|
|
||||||
t.Logf("Using temp file %v", tmpFile)
|
|
||||||
for i, table := range writeFileIfChangedTests {
|
|
||||||
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
|
|
||||||
err := ioutil.WriteFile(tmpFile, table.before, 0600)
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
defer os.Remove(tmpFile)
|
|
||||||
fi, err := os.Stat(tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
beforeMod := fi.ModTime()
|
|
||||||
err = writeFileIfChanged(tmpFile, table.after, 0600)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
fi, err = os.Stat(tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
afterMod := fi.ModTime()
|
|
||||||
if table.same {
|
|
||||||
if beforeMod != afterMod {
|
|
||||||
t.Errorf("Expected file timestamps to be the same (%v); got %v", beforeMod, afterMod)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if beforeMod == afterMod {
|
|
||||||
t.Errorf("Expected file timestamp to be different got %v and %v", beforeMod, afterMod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#*******************************************************************#
|
|
||||||
#* Module Name: qm.ini *#
|
|
||||||
#* Type : IBM MQ queue manager configuration file *#
|
|
||||||
# Function : Define the configuration of a single queue manager *#
|
|
||||||
#* *#
|
|
||||||
#*******************************************************************#
|
|
||||||
#* Notes : *#
|
|
||||||
#* 1) This file defines the configuration of the queue manager *#
|
|
||||||
#* *#
|
|
||||||
#*******************************************************************#
|
|
||||||
ExitPath:
|
|
||||||
ExitsDefaultPath=C:\ProgramData\IBM\MQ\exits
|
|
||||||
ExitsDefaultPath64=C:\ProgramData\IBM\MQ\exits64
|
|
||||||
InstanceData:
|
|
||||||
InstanceID=1562831591
|
|
||||||
Startup=ServiceManual
|
|
||||||
#* *#
|
|
||||||
#* *#
|
|
||||||
Log:
|
|
||||||
LogPrimaryFiles=3
|
|
||||||
LogSecondaryFiles=2
|
|
||||||
LogFilePages=4096
|
|
||||||
LogType=CIRCULAR
|
|
||||||
LogBufferPages=0
|
|
||||||
LogPath=C:\ProgramData\IBM\MQ\log\INI1\
|
|
||||||
LogWriteIntegrity=TripleWrite
|
|
||||||
Service:
|
|
||||||
Name=AuthorizationService
|
|
||||||
EntryPoints=14
|
|
||||||
ServiceComponent:
|
|
||||||
Service=AuthorizationService
|
|
||||||
Name=MQSeries.WindowsNT.auth.service
|
|
||||||
Module=amqzfu.dll
|
|
||||||
ComponentDataSize=0
|
|
||||||
Channels:
|
|
||||||
ChlauthEarlyAdopt=Y
|
|
||||||
TCP:
|
|
||||||
SndBuffSize=0
|
|
||||||
RcvBuffSize=0
|
|
||||||
RcvSndBuffSize=0
|
|
||||||
RcvRcvBuffSize=0
|
|
||||||
ClntSndBuffSize=0
|
|
||||||
ClntRcvBuffSize=0
|
|
||||||
SvrSndBuffSize=0
|
|
||||||
SvrRcvBuffSize=0
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ApiExitLocal:
|
|
||||||
Sequence=1
|
|
||||||
Function=EntryPoint
|
|
||||||
Module=/opt/mqm/exitlib.so
|
|
||||||
Name=mylib
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
AllActivityTrace:
|
|
||||||
ActivityInterval=11
|
|
||||||
ActivityCount=1
|
|
||||||
TraceLevel=INFO
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsget
|
|
||||||
Trace=ON
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
ApiExitLocal:
|
|
||||||
Sequence=1
|
|
||||||
Function=EntryPoint
|
|
||||||
Module=/opt/foo/foo.so
|
|
||||||
Name=FooExit
|
|
||||||
Channels:
|
|
||||||
MQIBindType=FASTPATH
|
|
||||||
Log:
|
|
||||||
LogPrimaryFiles=30
|
|
||||||
LogType=CIRCULAR
|
|
||||||
LogPath=/ProgramfILES/IBM/MQ/log/INI1/
|
|
||||||
TCP:
|
|
||||||
SndBuffSize=4095
|
|
||||||
RcvBuffSize=4095
|
|
||||||
RcvSndBuffSize=4095
|
|
||||||
RcvRcvBuffSize=4095
|
|
||||||
ClntSndBuffSize=2049
|
|
||||||
ClntRcvBuffSize=2049
|
|
||||||
SvrSndBuffSize=2049
|
|
||||||
SvrRcvBuffSize=2049
|
|
||||||
ApplicationTrace:
|
|
||||||
ApplName=amqsput
|
|
||||||
Trace=ON
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
|
||||||
"github.com/ibm-messaging/mq-container/pkg/logger"
|
"github.com/ibm-messaging/mq-container/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,16 +44,6 @@ func ProcessTemplateFile(templateFile, destFile string, data interface{}, log *l
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
return 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 {
|
} else {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -67,15 +56,5 @@ func ProcessTemplateFile(templateFile, destFile string, data interface{}, log *l
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
return 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
51
internal/mqversion/mqversion.go
Normal file
51
internal/mqversion/mqversion.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
© 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 mqversion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ibm-messaging/mq-container/internal/command"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get will return the current MQ version
|
||||||
|
func Get() (string, error) {
|
||||||
|
mqVersion, _, err := command.Run("dspmqver", "-b", "-f", "2")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error Getting MQ version: %v", err)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(mqVersion), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare returns an integer comparing two MQ version strings lexicographically. The result will be 0 if currentVersion==checkVersion, -1 if currentVersion < checkVersion, and +1 if currentVersion > checkVersion
|
||||||
|
func Compare(checkVersion string) (int, error) {
|
||||||
|
currentVersion, err := Get()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
// trim any suffix from MQ version x.x.x.x
|
||||||
|
currentVersion = currentVersion[0:7]
|
||||||
|
if currentVersion < checkVersion {
|
||||||
|
return -1, nil
|
||||||
|
} else if currentVersion == checkVersion {
|
||||||
|
return 0, nil
|
||||||
|
} else if currentVersion > checkVersion {
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("Failed to compare MQ versions")
|
||||||
|
}
|
||||||
55
internal/mqversion/mqversion_test.go
Normal file
55
internal/mqversion/mqversion_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 mqversion
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestCompareLower(t *testing.T) {
|
||||||
|
checkVersion := "9.9.9.9"
|
||||||
|
mqVersionCheck, err := Compare(checkVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to compare MQ versions: %v", err)
|
||||||
|
}
|
||||||
|
if mqVersionCheck != -1 {
|
||||||
|
t.Errorf("MQ version compare result failed. Expected -1, Got %v", mqVersionCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareHigher(t *testing.T) {
|
||||||
|
checkVersion := "1.1.1.1"
|
||||||
|
mqVersionCheck, err := Compare(checkVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to compare MQ versions: %v", err)
|
||||||
|
}
|
||||||
|
if mqVersionCheck != 1 {
|
||||||
|
t.Errorf("MQ version compare result failed. Expected 1, Got %v", mqVersionCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareEqual(t *testing.T) {
|
||||||
|
checkVersion, err := Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get current MQ version: %v", err)
|
||||||
|
}
|
||||||
|
mqVersionCheck, err := Compare(checkVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to compare MQ versions: %v", err)
|
||||||
|
}
|
||||||
|
if mqVersionCheck != 0 {
|
||||||
|
t.Errorf("MQ version compare result failed. Expected 0, Got %v", mqVersionCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,6 +76,11 @@ func IsRunningAsStandbyQM(name string) (bool, error) {
|
|||||||
return isRunningQM(name, "(RUNNING AS STANDBY)")
|
return isRunningQM(name, "(RUNNING AS STANDBY)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRunningAsReplicaQM returns true if the queue manager is running in replica mode
|
||||||
|
func IsRunningAsReplicaQM(name string) (bool, error) {
|
||||||
|
return isRunningQM(name, "(REPLICA)")
|
||||||
|
}
|
||||||
|
|
||||||
func isRunningQM(name string, status string) (bool, error) {
|
func isRunningQM(name string, status string) (bool, error) {
|
||||||
out, _, err := command.Run("dspmq", "-n", "-m", name)
|
out, _, err := command.Run("dspmq", "-n", "-m", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
1012
internal/tls/tls.go
1012
internal/tls/tls.go
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, 2021
|
||||||
|
|
||||||
|
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(keystoreDirDefault, 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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,66 +16,26 @@ limitations under the License.
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"golang.org/x/sys/unix"
|
||||||
"os/user"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// User holds information on primary and supplemental OS groups
|
// User holds information on primary and supplemental OS groups
|
||||||
type User struct {
|
type User struct {
|
||||||
UID string
|
UID int
|
||||||
Name string
|
PrimaryGID int
|
||||||
PrimaryGID string
|
SupplementalGID []int
|
||||||
SupplementalGID []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUser returns the current user and group information
|
// GetUser returns the current user and group information
|
||||||
func GetUser() (User, error) {
|
func GetUser() (User, error) {
|
||||||
u, err := user.Current()
|
u := User{
|
||||||
|
UID: unix.Geteuid(),
|
||||||
|
PrimaryGID: unix.Getgid(),
|
||||||
|
}
|
||||||
|
groups, err := unix.Getgroups()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return User{}, err
|
return u, err
|
||||||
}
|
}
|
||||||
g, err := getCurrentUserGroups()
|
u.SupplementalGID = groups
|
||||||
if err != nil {
|
return u, 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
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Fat manifests
|
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:
|
They are used in conjunction with [manifest-tool](https://github.com/estesp/manifest-tool), for example:
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# © Copyright IBM Corporation 2018
|
# © Copyright IBM Corporation 2020
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,18 +12,17 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
image: ibmcorp/mqadvanced-server-dev:9.1.1.0
|
image: ibmcom/mq:9.1.5.0-r1
|
||||||
manifests:
|
manifests:
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-x86_64
|
- image: ibmcom/mq:9.1.5.0-r1-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-ppc64le
|
- image: ibmcom/mq:9.1.5.0-r1-ppc64le
|
||||||
platform:
|
platform:
|
||||||
architecture: ppc64le
|
architecture: ppc64le
|
||||||
os: linux
|
os: linux
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.1.0-s390x
|
- image: ibmcom/mq:9.1.5.0-r1-s390x
|
||||||
platform:
|
platform:
|
||||||
architecture: s390x
|
architecture: s390x
|
||||||
os: linux
|
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");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,18 +12,9 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
image: ibmcorp/mqadvanced-server-dev:9.1.0.0
|
image: ibmcom/mq:9.2.0.0-r1
|
||||||
manifests:
|
manifests:
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.0.0-x86_64
|
- image: ibmcom/mq:9.2.0.0-r1-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
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");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -14,15 +14,7 @@
|
|||||||
|
|
||||||
image: ibmcom/mq:latest
|
image: ibmcom/mq:latest
|
||||||
manifests:
|
manifests:
|
||||||
- image: ibmcom/mq:9.1.4.0-r1-amd64
|
- image: ibmcom/mq:9.2.0.0-r1-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
- image: ibmcom/mq:9.1.4.0-r1-ppc64le
|
|
||||||
platform:
|
|
||||||
architecture: ppc64le
|
|
||||||
os: linux
|
|
||||||
- image: ibmcom/mq:9.1.4.0-r1-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,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.3.0-r3
|
|
||||||
manifests:
|
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-ppc64le
|
|
||||||
platform:
|
|
||||||
architecture: ppc64le
|
|
||||||
os: linux
|
|
||||||
- image: ibmcorp/mqadvanced-server-dev:9.1.3.0-r3-s390x
|
|
||||||
platform:
|
|
||||||
architecture: s390x
|
|
||||||
os: linux
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2017, 2019
|
© Copyright IBM Corporation 2017, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -45,11 +45,14 @@ func LogContainerDetails(log *logger.Logger) error {
|
|||||||
log.Printf("Base image: %v", bi)
|
log.Printf("Base image: %v", bi)
|
||||||
}
|
}
|
||||||
u, err := user.GetUser()
|
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 err == nil {
|
||||||
if len(u.SupplementalGID) == 0 {
|
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 {
|
} 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()
|
caps, err := containerruntime.GetCapabilities()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -117,14 +117,22 @@ func (l *Logger) log(level string, msg string) {
|
|||||||
// Debug logs a line as debug
|
// Debug logs a line as debug
|
||||||
func (l *Logger) Debug(args ...interface{}) {
|
func (l *Logger) Debug(args ...interface{}) {
|
||||||
if l.debug {
|
if l.debug {
|
||||||
l.log(debugLevel, fmt.Sprint(args...))
|
if l.json {
|
||||||
|
l.log(debugLevel, fmt.Sprint(args...))
|
||||||
|
} else {
|
||||||
|
l.log(debugLevel, "DEBUG: "+fmt.Sprint(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf logs a line as debug using format specifiers
|
// Debugf logs a line as debug using format specifiers
|
||||||
func (l *Logger) Debugf(format string, args ...interface{}) {
|
func (l *Logger) Debugf(format string, args ...interface{}) {
|
||||||
if l.debug {
|
if l.debug {
|
||||||
l.log(debugLevel, fmt.Sprintf(format, args...))
|
if l.json {
|
||||||
|
l.log(debugLevel, fmt.Sprintf(format, args...))
|
||||||
|
} else {
|
||||||
|
l.log(debugLevel, fmt.Sprintf("DEBUG: "+format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
114
test/docker/Gopkg.lock
generated
114
test/docker/Gopkg.lock
generated
@@ -1,114 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/Azure/go-ansiterm"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"winterm"
|
|
||||||
]
|
|
||||||
revision = "d6e3b3328b783f23731bc4d058875b0371ff8109"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/Microsoft/go-winio"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
|
||||||
version = "v0.4.7"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/Sirupsen/logrus"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
|
||||||
version = "v1.0.5"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/docker/distribution"
|
|
||||||
packages = [
|
|
||||||
"digest",
|
|
||||||
"reference"
|
|
||||||
]
|
|
||||||
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
|
|
||||||
version = "v2.6.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/docker/docker"
|
|
||||||
packages = [
|
|
||||||
"api/types",
|
|
||||||
"api/types/blkiodev",
|
|
||||||
"api/types/container",
|
|
||||||
"api/types/events",
|
|
||||||
"api/types/filters",
|
|
||||||
"api/types/mount",
|
|
||||||
"api/types/network",
|
|
||||||
"api/types/reference",
|
|
||||||
"api/types/registry",
|
|
||||||
"api/types/strslice",
|
|
||||||
"api/types/swarm",
|
|
||||||
"api/types/time",
|
|
||||||
"api/types/versions",
|
|
||||||
"api/types/volume",
|
|
||||||
"client",
|
|
||||||
"pkg/jsonlog",
|
|
||||||
"pkg/jsonmessage",
|
|
||||||
"pkg/stdcopy",
|
|
||||||
"pkg/term",
|
|
||||||
"pkg/term/windows",
|
|
||||||
"pkg/tlsconfig"
|
|
||||||
]
|
|
||||||
revision = "f5ec1e2936dcbe7b5001c2b817188b095c700c27"
|
|
||||||
version = "v17.03.2-ce"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/docker/go-connections"
|
|
||||||
packages = [
|
|
||||||
"nat",
|
|
||||||
"sockets",
|
|
||||||
"tlsconfig"
|
|
||||||
]
|
|
||||||
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
|
||||||
version = "v0.3.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/docker/go-units"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52"
|
|
||||||
version = "v0.3.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/pkg/errors"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
|
||||||
version = "v0.8.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
packages = ["ssh/terminal"]
|
|
||||||
revision = "88942b9c40a4c9d203b82b3731787b672d6e809b"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = [
|
|
||||||
"context",
|
|
||||||
"context/ctxhttp",
|
|
||||||
"proxy"
|
|
||||||
]
|
|
||||||
revision = "6078986fec03a1dcc236c34816c71b0e05018fda"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = [
|
|
||||||
"unix",
|
|
||||||
"windows"
|
|
||||||
]
|
|
||||||
revision = "13d03a9a82fba647c21a0ef8fba44a795d0f0835"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "c792836365447209421d5dc68a75fa77063408b8a6a2f9325b976581a0d60107"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build mqdev
|
// +build mqdev
|
||||||
|
|
||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -43,6 +43,7 @@ func TestDevGoldenPath(t *testing.T) {
|
|||||||
Env: []string{
|
Env: []string{
|
||||||
"LICENSE=accept",
|
"LICENSE=accept",
|
||||||
"MQ_QMGR_NAME=" + qm,
|
"MQ_QMGR_NAME=" + qm,
|
||||||
|
"DEBUG=true",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
|
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
|
||||||
@@ -81,16 +82,16 @@ func TestDevSecure(t *testing.T) {
|
|||||||
"LICENSE=accept",
|
"LICENSE=accept",
|
||||||
"MQ_QMGR_NAME=" + qm,
|
"MQ_QMGR_NAME=" + qm,
|
||||||
"MQ_APP_PASSWORD=" + appPassword,
|
"MQ_APP_PASSWORD=" + appPassword,
|
||||||
"MQ_TLS_KEYSTORE=/var/tls/server.p12",
|
|
||||||
"MQ_TLS_PASSPHRASE=" + tlsPassPhrase,
|
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
|
"WLP_LOGGING_MESSAGE_FORMAT=JSON",
|
||||||
|
"MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG=true",
|
||||||
},
|
},
|
||||||
Image: imageName(),
|
Image: imageName(),
|
||||||
}
|
}
|
||||||
hostConfig := container.HostConfig{
|
hostConfig := container.HostConfig{
|
||||||
Binds: []string{
|
Binds: []string{
|
||||||
coverageBind(t),
|
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
|
// Assign a random port for the web server on the host
|
||||||
// TODO: Don't do this for all tests
|
// TODO: Don't do this for all tests
|
||||||
@@ -145,7 +146,7 @@ func TestDevWebDisabled(t *testing.T) {
|
|||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(t, cli, id)
|
waitForReady(t, cli, id)
|
||||||
t.Run("Web", func(t *testing.T) {
|
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") {
|
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)
|
t.Errorf("Expected dspmqweb to say 'Server is not running' or 'MQWB1125I'; got \"%v\"", dspmqweb)
|
||||||
}
|
}
|
||||||
@@ -176,7 +177,7 @@ func TestDevConfigDisabled(t *testing.T) {
|
|||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(t, cli, id)
|
waitForReady(t, cli, id)
|
||||||
waitForWebReady(t, cli, id, insecureTLSConfig)
|
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 {
|
if rc == 0 {
|
||||||
t.Errorf("Expected DEV queues to be missing")
|
t.Errorf("Expected DEV queues to be missing")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build mqdev
|
// +build mqdev
|
||||||
|
|
||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018, 2019
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -48,8 +48,9 @@ var insecureTLSConfig *tls.Config = &tls.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
|
func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
|
||||||
|
t.Logf("%s Waiting for web server to be ready", time.Now().Format(time.RFC3339))
|
||||||
httpClient := http.Client{
|
httpClient := http.Client{
|
||||||
Timeout: time.Duration(3 * time.Second),
|
Timeout: time.Duration(10 * time.Second),
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: tlsConfig,
|
TLSClientConfig: tlsConfig,
|
||||||
},
|
},
|
||||||
@@ -63,13 +64,13 @@ func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls
|
|||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
req.SetBasicAuth("admin", defaultAdminPassword)
|
req.SetBasicAuth("admin", defaultAdminPassword)
|
||||||
resp, err := httpClient.Do(req.WithContext(ctx))
|
resp, err := httpClient.Do(req)
|
||||||
if err == nil && resp.StatusCode == http.StatusOK {
|
if err == nil && resp.StatusCode == http.StatusOK {
|
||||||
t.Log("MQ web server is ready")
|
t.Logf("%s MQ web server is ready", time.Now().Format(time.RFC3339))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
t.Fatal("Timed out waiting for web server to become ready")
|
t.Fatalf("%s Timed out waiting for web server to become ready", time.Now().Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,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
|
// 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) {
|
func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, password string) {
|
||||||
containerConfig := container.Config{
|
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{
|
Env: []string{
|
||||||
"MQ_PORT_1414_TCP_ADDR=" + getIPAddress(t, cli, ID),
|
"MQ_PORT_1414_TCP_ADDR=" + getIPAddress(t, cli, ID),
|
||||||
"MQ_USERNAME=" + user,
|
"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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -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
|
// TestGoldenPath starts a queue manager successfully when metrics are enabled
|
||||||
func TestGoldenPathWithMetrics(t *testing.T) {
|
func TestGoldenPathWithMetrics(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@@ -159,7 +182,7 @@ func utilTestNoQueueManagerName(t *testing.T, hostName string, expectedName stri
|
|||||||
id := runContainer(t, cli, &containerConfig)
|
id := runContainer(t, cli, &containerConfig)
|
||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(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) {
|
if !strings.Contains(out, search) {
|
||||||
t.Errorf("Expected result of running dspmq to contain name=%v, got name=%v", search, out)
|
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
|
FROM %v
|
||||||
USER root
|
USER root
|
||||||
RUN echo '#!/bin/bash\nexit 999' > /opt/mqm/bin/crtmqm
|
RUN echo '#!/bin/bash\nexit 999' > /opt/mqm/bin/crtmqm
|
||||||
RUN chown mqm:mqm /opt/mqm/bin/crtmqm
|
USER 1001`, imageName())},
|
||||||
RUN chmod 6550 /opt/mqm/bin/crtmqm
|
|
||||||
USER mqm`, imageName())},
|
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
defer deleteImage(t, cli, tag)
|
defer deleteImage(t, cli, tag)
|
||||||
@@ -426,9 +447,7 @@ func TestStartQueueManagerFail(t *testing.T) {
|
|||||||
FROM %v
|
FROM %v
|
||||||
USER root
|
USER root
|
||||||
RUN echo '#!/bin/bash\ndltmqm $@ && strmqm $@' > /opt/mqm/bin/strmqm
|
RUN echo '#!/bin/bash\ndltmqm $@ && strmqm $@' > /opt/mqm/bin/strmqm
|
||||||
RUN chown mqm:mqm /opt/mqm/bin/strmqm
|
USER 1001`, imageName())},
|
||||||
RUN chmod 6550 /opt/mqm/bin/strmqm
|
|
||||||
USER mqm`, imageName())},
|
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
defer deleteImage(t, cli, tag)
|
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)
|
t.Fatalf("Expected umount to work with rc=0, got %v. Output was: %s", rc, out)
|
||||||
}
|
}
|
||||||
time.Sleep(3 * time.Second)
|
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 {
|
if rc == 0 {
|
||||||
t.Errorf("Expected chkmqhealthy to fail")
|
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)
|
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)
|
t.Logf(ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,14 +537,14 @@ func TestZombies(t *testing.T) {
|
|||||||
waitForReady(t, cli, id)
|
waitForReady(t, cli, id)
|
||||||
// Kill an MQ process with children. After it is killed, its children
|
// 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.
|
// 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" {
|
if out == "0" {
|
||||||
t.Log("Failed to kill process 'amqzxma0'")
|
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)
|
t.Fatalf("Here is a list of currently running processes:\n%s", out)
|
||||||
}
|
}
|
||||||
time.Sleep(3 * time.Second)
|
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 != "" {
|
if out != "" {
|
||||||
count := strings.Count(out, "\n") + 1
|
count := strings.Count(out, "\n") + 1
|
||||||
t.Errorf("Expected zombies=0, got %v", count)
|
t.Errorf("Expected zombies=0, got %v", count)
|
||||||
@@ -552,7 +571,7 @@ func TestMQSC(t *testing.T) {
|
|||||||
RUN rm -f /etc/mqm/*.mqsc
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD test.mqsc /etc/mqm/
|
ADD test.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||||
USER mqm`, imageName())},
|
USER 1001`, imageName())},
|
||||||
{"test.mqsc", "DEFINE QLOCAL(test)"},
|
{"test.mqsc", "DEFINE QLOCAL(test)"},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -565,7 +584,16 @@ func TestMQSC(t *testing.T) {
|
|||||||
id := runContainer(t, cli, &containerConfig)
|
id := runContainer(t, cli, &containerConfig)
|
||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(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 {
|
if rc != 0 {
|
||||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
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))
|
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
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD test.mqsc /etc/mqm/
|
ADD test.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||||
USER mqm`, imageName())},
|
USER 1001`, imageName())},
|
||||||
{"test.mqsc", buf.String()},
|
{"test.mqsc", buf.String()},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -609,7 +637,15 @@ func TestLargeMQSC(t *testing.T) {
|
|||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(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 {
|
if rc != 0 {
|
||||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
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))
|
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
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD test.mqsc /etc/mqm/
|
ADD test.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||||
USER mqm`, imageName())},
|
USER 1001`, imageName())},
|
||||||
{"test.mqsc", buf.String()},
|
{"test.mqsc", buf.String()},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -739,7 +775,7 @@ func TestRedactInvalidMQSC(t *testing.T) {
|
|||||||
RUN rm -f /etc/mqm/*.mqsc
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD test.mqsc /etc/mqm/
|
ADD test.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||||
USER mqm`, imageName())},
|
USER 1001`, imageName())},
|
||||||
{"test.mqsc", buf.String()},
|
{"test.mqsc", buf.String()},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -785,7 +821,7 @@ func TestInvalidMQSC(t *testing.T) {
|
|||||||
RUN rm -f /etc/mqm/*.mqsc
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD mqscTest.mqsc /etc/mqm/
|
ADD mqscTest.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/mqscTest.mqsc
|
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"},
|
{"mqscTest.mqsc", "DEFINE INVALIDLISTENER('TEST.LISTENER.TCP') TRPTYPE(TCP) PORT(1414) CONTROL(QMGR) REPLACE"},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -804,6 +840,187 @@ func TestInvalidMQSC(t *testing.T) {
|
|||||||
expectTerminationMessage(t, cli, id)
|
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
|
// TestReadiness creates a new image with large amounts of MQSC in, to
|
||||||
// ensure that the readiness check doesn't pass until configuration has finished.
|
// 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.
|
// 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
|
RUN rm -f /etc/mqm/*.mqsc
|
||||||
ADD test.mqsc /etc/mqm/
|
ADD test.mqsc /etc/mqm/
|
||||||
RUN chmod 0660 /etc/mqm/test.mqsc
|
RUN chmod 0660 /etc/mqm/test.mqsc
|
||||||
USER mqm`, imageName())},
|
USER 1001`, imageName())},
|
||||||
{"test.mqsc", buf.String()},
|
{"test.mqsc", buf.String()},
|
||||||
}
|
}
|
||||||
tag := createImage(t, cli, files)
|
tag := createImage(t, cli, files)
|
||||||
@@ -841,20 +1058,27 @@ func TestReadiness(t *testing.T) {
|
|||||||
id := runContainer(t, cli, &containerConfig)
|
id := runContainer(t, cli, &containerConfig)
|
||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
queueCheckCommand := fmt.Sprintf("echo 'DISPLAY QLOCAL(test%v)' | runmqsc", numQueues)
|
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)
|
t.Log(mqsc)
|
||||||
for {
|
for {
|
||||||
readyRC, _ := execContainer(t, cli, id, "mqm", []string{"chkmqready"})
|
readyRC, _ := execContainer(t, cli, id, "", []string{"chkmqready"})
|
||||||
queueCheckRC, queueCheckOut := execContainer(t, cli, id, "mqm", []string{"bash", "-c", queueCheckCommand})
|
|
||||||
t.Logf("readyRC=%v,queueCheckRC=%v\n", readyRC, queueCheckRC)
|
|
||||||
|
|
||||||
if readyRC == 0 {
|
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 {
|
if queueCheckRC != 0 {
|
||||||
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
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)
|
t.Fatalf("Runmqsc returned %v with error %v. chkmqready returned %v when MQSC had not finished", queueCheckRC, r.FindString(queueCheckOut), readyRC)
|
||||||
} else {
|
} else {
|
||||||
// chkmqready says OK, and the last queue exists, so return
|
// 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)
|
t.Log(runmqsc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -863,6 +1087,7 @@ func TestReadiness(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorLogRotation(t *testing.T) {
|
func TestErrorLogRotation(t *testing.T) {
|
||||||
|
t.Skipf("Skipping %v until test defect fixed", t.Name())
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
cli, err := client.NewEnvClient()
|
cli, err := client.NewEnvClient()
|
||||||
@@ -903,7 +1128,7 @@ func TestErrorLogRotation(t *testing.T) {
|
|||||||
for {
|
for {
|
||||||
execContainer(t, cli, id, "fred", []string{"bash", "-c", "/opt/mqm/samp/bin/amqsput FAKE"})
|
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)
|
amqerr02size, _ := strconv.Atoi(atoiStr)
|
||||||
|
|
||||||
if amqerr02size > 0 {
|
if amqerr02size > 0 {
|
||||||
@@ -911,7 +1136,7 @@ func TestErrorLogRotation(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, out := execContainer(t, cli, id, "root", []string{"ls", "-l", dir})
|
_, out := execContainer(t, cli, id, "", []string{"ls", "-l", dir})
|
||||||
t.Log(out)
|
t.Log(out)
|
||||||
stopContainer(t, cli, id)
|
stopContainer(t, cli, id)
|
||||||
b := copyFromContainer(t, cli, id, filepath.Join(dir, "AMQERR01.json"))
|
b := copyFromContainer(t, cli, id, filepath.Join(dir, "AMQERR01.json"))
|
||||||
@@ -1055,7 +1280,7 @@ func TestCorrectLicense(t *testing.T) {
|
|||||||
defer cleanContainer(t, cli, id)
|
defer cleanContainer(t, cli, id)
|
||||||
waitForReady(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 {
|
if rc != 0 {
|
||||||
t.Fatalf("Failed to get license string. RC=%d. Output=%s", rc, license)
|
t.Fatalf("Failed to get license string. RC=%d. Output=%s", rc, license)
|
||||||
}
|
}
|
||||||
@@ -1185,3 +1410,109 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// utilTestStartedCheck is used by TestStartedCheck* to run a container with
|
||||||
|
// privileges enabled or disabled. Otherwise the same as the golden path tests.
|
||||||
|
func utilTestStartedCheck(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{"chkmqstarted"})
|
||||||
|
t.Log(out)
|
||||||
|
if rc != 0 {
|
||||||
|
t.Errorf("Expected chkmqstarted to return with exit code 0; got \"%v\"", rc)
|
||||||
|
t.Logf("Output from chkmqstarted:\n%v", out)
|
||||||
|
}
|
||||||
|
// Stop the container cleanly
|
||||||
|
stopContainer(t, cli, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestStartedCheckWithNoNewPrivileges tests golden path start/stop plus
|
||||||
|
// chkmqstarted, when running in a container where no new privileges are
|
||||||
|
// allowed (i.e. setuid is disabled)
|
||||||
|
func TestStartedCheckWithNoNewPrivileges(t *testing.T) {
|
||||||
|
utilTestStartedCheck(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestStartedCheckWithNoNewPrivileges tests golden path start/stop plus
|
||||||
|
// chkmqstarted 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 TestStartedCheckWithNewPrivileges(t *testing.T) {
|
||||||
|
utilTestStartedCheck(t, false)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2017, 2019
|
© Copyright IBM Corporation 2017, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"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.
|
func generateRandomUID() string {
|
||||||
// If no image is specified in the container config, then the image name is retrieved from the TEST_IMAGE
|
rand.Seed(time.Now().UnixNano())
|
||||||
// environment variable.
|
min := 1000
|
||||||
func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *container.Config, ports []int) string {
|
max := 9999
|
||||||
if containerConfig.Image == "" {
|
return fmt.Sprint(rand.Intn(max-min) + min)
|
||||||
containerConfig.Image = imageName()
|
}
|
||||||
}
|
|
||||||
// Always run as the "mqm" user, unless the test has specified otherwise
|
// getDefaultHostConfig creates a HostConfig and populates it with the defaults used in testing
|
||||||
if containerConfig.User == "" {
|
func getDefaultHostConfig(t *testing.T, cli *client.Client) *container.HostConfig {
|
||||||
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))
|
|
||||||
hostConfig := container.HostConfig{
|
hostConfig := container.HostConfig{
|
||||||
Binds: []string{
|
Binds: []string{
|
||||||
coverageBind(t),
|
coverageBind(t),
|
||||||
@@ -281,15 +277,9 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
|||||||
CapDrop: []string{
|
CapDrop: []string{
|
||||||
"ALL",
|
"ALL",
|
||||||
},
|
},
|
||||||
|
Privileged: false,
|
||||||
}
|
}
|
||||||
if devImage(t, cli) {
|
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
|
// Only needed for a RHEL-based image
|
||||||
if baseImage(t, cli) != "ubuntu" {
|
if baseImage(t, cli) != "ubuntu" {
|
||||||
hostConfig.CapAdd = append(hostConfig.CapAdd, "DAC_OVERRIDE")
|
hostConfig.CapAdd = append(hostConfig.CapAdd, "DAC_OVERRIDE")
|
||||||
@@ -297,6 +287,62 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
|||||||
} else {
|
} else {
|
||||||
t.Logf("Detected MQ Advanced image - dropping all capabilities")
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// runContainerWithAllConfig creates and starts a container, using the supplied ContainerConfig, HostConfig,
|
||||||
|
// NetworkingConfig, and container name (or the value of t.Name if containerName="").
|
||||||
|
func runContainerWithAllConfig(t *testing.T, cli *client.Client, containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) string {
|
||||||
|
if containerName == "" {
|
||||||
|
containerName = t.Name()
|
||||||
|
}
|
||||||
|
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))
|
||||||
|
t.Logf("Running container (%s)", containerConfig.Image)
|
||||||
|
ctr, err := cli.ContainerCreate(context.Background(), containerConfig, hostConfig, networkingConfig, containerName)
|
||||||
|
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 {
|
for _, p := range ports {
|
||||||
port := nat.Port(fmt.Sprintf("%v/tcp", p))
|
port := nat.Port(fmt.Sprintf("%v/tcp", p))
|
||||||
hostConfig.PortBindings[port] = []nat.PortBinding{
|
hostConfig.PortBindings[port] = []nat.PortBinding{
|
||||||
@@ -305,14 +351,7 @@ func runContainerWithPorts(t *testing.T, cli *client.Client, containerConfig *co
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
networkingConfig := network.NetworkingConfig{}
|
return runContainerWithHostConfig(t, cli, containerConfig, hostConfig)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// runContainer creates and starts a container. If no image is specified in
|
// runContainer creates and starts a container. If no image is specified in
|
||||||
@@ -524,6 +563,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
|
// 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) {
|
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{
|
config := types.ExecConfig{
|
||||||
User: user,
|
User: user,
|
||||||
Privileged: false,
|
Privileged: false,
|
||||||
@@ -592,19 +632,24 @@ func execContainer(t *testing.T, cli *client.Client, ID string, user string, cmd
|
|||||||
}
|
}
|
||||||
|
|
||||||
func waitForReady(t *testing.T, cli *client.Client, ID string) {
|
func waitForReady(t *testing.T, cli *client.Client, ID string) {
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
rc, _ := execContainer(t, cli, ID, "mqm", []string{"chkmqready"})
|
rc, _ := execContainer(t, cli, ID, "", []string{"chkmqready"})
|
||||||
|
|
||||||
if rc == 0 {
|
if rc == 0 {
|
||||||
t.Log("MQ is ready")
|
t.Log("MQ is ready")
|
||||||
return
|
return
|
||||||
} else if rc == 10 {
|
} else if rc == 10 {
|
||||||
t.Log("MQ Readiness: Queue Manager Running as Standby")
|
t.Log("MQ Readiness: Queue Manager Running as Standby")
|
||||||
return
|
return
|
||||||
|
} else if rc == 20 {
|
||||||
|
t.Log("MQ Readiness: Queue Manager Running as Replica")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
t.Fatal("Timed out waiting for container to become ready")
|
t.Fatal("Timed out waiting for container to become ready")
|
||||||
@@ -819,3 +864,12 @@ func countTarLines(t *testing.T, b []byte) int {
|
|||||||
}
|
}
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMQVersion(t *testing.T, cli *client.Client) (string, error) {
|
||||||
|
inspect, _, err := cli.ImageInspectWithRaw(context.Background(), imageName())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
version := inspect.ContainerConfig.Labels["version"]
|
||||||
|
return version, nil
|
||||||
|
}
|
||||||
|
|||||||
20
test/docker/go.mod
Normal file
20
test/docker/go.mod
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
module github.com/ibm-messaging/mq-container/test/docker
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||||
|
github.com/Sirupsen/logrus v1.0.5 // indirect
|
||||||
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
|
github.com/docker/docker v1.13.2-0.20170601211448-f5ec1e2936dc
|
||||||
|
github.com/docker/go-connections v0.4.0
|
||||||
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
|
github.com/onsi/ginkgo v1.14.1 // indirect
|
||||||
|
github.com/onsi/gomega v1.10.2 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/spf13/cobra v1.1.1 // indirect
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
|
||||||
|
)
|
||||||
366
test/docker/go.sum
Normal file
366
test/docker/go.sum
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||||
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/Sirupsen/logrus v1.0.5 h1:447dy9LxSj+Iaa2uN3yoFHOzU9yJcJYiQPtNz8OXtv0=
|
||||||
|
github.com/Sirupsen/logrus v1.0.5/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/docker v1.13.2-0.20170601211448-f5ec1e2936dc h1:y4nIGNQUH6JtUV3pd6HjnzdnHq+96wMDVXhkfZ6jc4E=
|
||||||
|
github.com/docker/docker v1.13.2-0.20170601211448-f5ec1e2936dc/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/docker v20.10.2+incompatible h1:vFgEHPqWBTp4pTjdLwjAA4bSo3gvIGOYwuJTlEjVBCw=
|
||||||
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||||
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
|
||||||
|
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
|
||||||
|
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||||
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
|
||||||
|
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||||
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2019
|
© Copyright IBM Corporation 2019, 2020
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -32,6 +32,7 @@ var miEnv = []string{
|
|||||||
// TestMultiInstanceStartStop creates 2 containers in a multi instance queue manager configuration
|
// TestMultiInstanceStartStop creates 2 containers in a multi instance queue manager configuration
|
||||||
// and starts/stop them checking we always have an active and standby
|
// and starts/stop them checking we always have an active and standby
|
||||||
func TestMultiInstanceStartStop(t *testing.T) {
|
func TestMultiInstanceStartStop(t *testing.T) {
|
||||||
|
t.Skipf("Skipping %v until test defect fixed", t.Name())
|
||||||
cli, err := client.NewEnvClient()
|
cli, err := client.NewEnvClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -76,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 {
|
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\(.*\)`)
|
regex := regexp.MustCompile(`STATUS\(.*\)`)
|
||||||
status := regex.FindString(dspmqOut)
|
status := regex.FindString(dspmqOut)
|
||||||
status = strings.TrimSuffix(strings.TrimPrefix(status, "STATUS("), ")")
|
status = strings.TrimSuffix(strings.TrimPrefix(status, "STATUS("), ")")
|
||||||
|
|||||||
219
test/docker/mq_native_ha_test.go
Normal file
219
test/docker/mq_native_ha_test.go
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestNativeHABasic creates 3 containers in a Native HA queue manager configuration
|
||||||
|
// and ensures the queue manger and replicas start as expected
|
||||||
|
func TestNativeHABasic(t *testing.T) {
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := getMQVersion(t, cli)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if version < "9.2.2.0" {
|
||||||
|
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
|
||||||
|
}
|
||||||
|
|
||||||
|
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
|
||||||
|
qmReplicaIDs := [3]string{}
|
||||||
|
qmVolumes := []string{}
|
||||||
|
qmNetwork, err := createBridgeNetwork(cli, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer removeBridgeNetwork(cli, qmNetwork.ID)
|
||||||
|
|
||||||
|
for i := 0; i <= 2; i++ {
|
||||||
|
vol := createVolume(t, cli, containerNames[i])
|
||||||
|
defer removeVolume(t, cli, vol.Name)
|
||||||
|
qmVolumes = append(qmVolumes, vol.Name)
|
||||||
|
|
||||||
|
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
|
||||||
|
hostConfig := getHostConfig(t, 1, "", "", vol.Name)
|
||||||
|
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
|
||||||
|
|
||||||
|
ctr := runContainerWithAllConfig(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
|
||||||
|
defer cleanContainer(t, cli, ctr)
|
||||||
|
qmReplicaIDs[i] = ctr
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForReadyHA(t, cli, qmReplicaIDs)
|
||||||
|
|
||||||
|
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNativeHAFailover creates 3 containers in a Native HA queue manager configuration,
|
||||||
|
// stops the active queue manager, checks a replica becomes active, and ensures the stopped
|
||||||
|
// queue manager comes back as a replica
|
||||||
|
func TestNativeHAFailover(t *testing.T) {
|
||||||
|
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := getMQVersion(t, cli)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if version < "9.2.2.0" {
|
||||||
|
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
|
||||||
|
}
|
||||||
|
|
||||||
|
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
|
||||||
|
qmReplicaIDs := [3]string{}
|
||||||
|
qmVolumes := []string{}
|
||||||
|
qmNetwork, err := createBridgeNetwork(cli, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer removeBridgeNetwork(cli, qmNetwork.ID)
|
||||||
|
|
||||||
|
for i := 0; i <= 2; i++ {
|
||||||
|
vol := createVolume(t, cli, containerNames[i])
|
||||||
|
defer removeVolume(t, cli, vol.Name)
|
||||||
|
qmVolumes = append(qmVolumes, vol.Name)
|
||||||
|
|
||||||
|
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
|
||||||
|
hostConfig := getHostConfig(t, 1, "", "", vol.Name)
|
||||||
|
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
|
||||||
|
|
||||||
|
ctr := runContainerWithAllConfig(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
|
||||||
|
defer cleanContainer(t, cli, ctr)
|
||||||
|
qmReplicaIDs[i] = ctr
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForReadyHA(t, cli, qmReplicaIDs)
|
||||||
|
|
||||||
|
haStatus, err := getActiveReplicaInstances(t, cli, qmReplicaIDs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stopContainer(t, cli, haStatus.Active)
|
||||||
|
waitForFailoverHA(t, cli, haStatus.Replica)
|
||||||
|
startContainer(t, cli, haStatus.Active)
|
||||||
|
waitForReady(t, cli, haStatus.Active)
|
||||||
|
|
||||||
|
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNativeHASecure creates 3 containers in a Native HA queue manager configuration
|
||||||
|
// with HA TLS enabled, and ensures the queue manger and replicas start as expected
|
||||||
|
func TestNativeHASecure(t *testing.T) {
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := getMQVersion(t, cli)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if version < "9.2.2.0" {
|
||||||
|
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
|
||||||
|
}
|
||||||
|
|
||||||
|
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
|
||||||
|
qmReplicaIDs := [3]string{}
|
||||||
|
qmNetwork, err := createBridgeNetwork(cli, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer removeBridgeNetwork(cli, qmNetwork.ID)
|
||||||
|
|
||||||
|
for i := 0; i <= 2; i++ {
|
||||||
|
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
|
||||||
|
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=true")
|
||||||
|
hostConfig := getNativeHASecureHostConfig(t)
|
||||||
|
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
|
||||||
|
|
||||||
|
ctr := runContainerWithAllConfig(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
|
||||||
|
defer cleanContainer(t, cli, ctr)
|
||||||
|
qmReplicaIDs[i] = ctr
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForReadyHA(t, cli, qmReplicaIDs)
|
||||||
|
|
||||||
|
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNativeHASecure creates 3 containers in a Native HA queue manager configuration
|
||||||
|
// with HA TLS enabled, overrides the default CipherSpec, and ensures the queue manger
|
||||||
|
// and replicas start as expected
|
||||||
|
func TestNativeHASecureCipherSpec(t *testing.T) {
|
||||||
|
cli, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := getMQVersion(t, cli)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if version < "9.2.2.0" {
|
||||||
|
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
|
||||||
|
}
|
||||||
|
|
||||||
|
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
|
||||||
|
qmReplicaIDs := [3]string{}
|
||||||
|
qmNetwork, err := createBridgeNetwork(cli, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer removeBridgeNetwork(cli, qmNetwork.ID)
|
||||||
|
|
||||||
|
for i := 0; i <= 2; i++ {
|
||||||
|
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
|
||||||
|
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=true", "MQ_NATIVE_HA_CIPHERSPEC=TLS_AES_256_GCM_SHA384")
|
||||||
|
hostConfig := getNativeHASecureHostConfig(t)
|
||||||
|
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
|
||||||
|
|
||||||
|
ctr := runContainerWithAllConfig(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
|
||||||
|
defer cleanContainer(t, cli, ctr)
|
||||||
|
qmReplicaIDs[i] = ctr
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForReadyHA(t, cli, qmReplicaIDs)
|
||||||
|
|
||||||
|
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
149
test/docker/mq_native_ha_test_util.go
Normal file
149
test/docker/mq_native_ha_test_util.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
© Copyright IBM Corporation 2021
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultHAPort = 9414
|
||||||
|
|
||||||
|
// HAReplicaStatus represents the Active/Replica/Replica container status of the queue manager
|
||||||
|
type HAReplicaStatus struct {
|
||||||
|
Active string
|
||||||
|
Replica [2]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBridgeNetwork(cli *client.Client, t *testing.T) (types.NetworkCreateResponse, error) {
|
||||||
|
return cli.NetworkCreate(context.Background(), t.Name(), types.NetworkCreate{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeBridgeNetwork(cli *client.Client, networkID string) error {
|
||||||
|
return cli.NetworkRemove(context.Background(), networkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNativeHAContainerConfig(containerName string, replicaNames [3]string, haPort int) container.Config {
|
||||||
|
return container.Config{
|
||||||
|
Env: []string{
|
||||||
|
"LICENSE=accept",
|
||||||
|
"MQ_QMGR_NAME=QM1",
|
||||||
|
"AMQ_CLOUD_PAK=true",
|
||||||
|
"MQ_NATIVE_HA=true",
|
||||||
|
fmt.Sprintf("HOSTNAME=%s", containerName),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_0_NAME=%s", replicaNames[0]),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_1_NAME=%s", replicaNames[1]),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_2_NAME=%s", replicaNames[2]),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS=%s(%d)", replicaNames[0], haPort),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS=%s(%d)", replicaNames[1], haPort),
|
||||||
|
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS=%s(%d)", replicaNames[2], haPort),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNativeHASecureHostConfig(t *testing.T) container.HostConfig {
|
||||||
|
return container.HostConfig{
|
||||||
|
Binds: []string{
|
||||||
|
coverageBind(t),
|
||||||
|
filepath.Join(getCwd(t, true), "../tls") + ":/etc/mqm/ha/pki/keys/ha",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNativeHANetworkConfig(networkID string) network.NetworkingConfig {
|
||||||
|
return network.NetworkingConfig{
|
||||||
|
EndpointsConfig: map[string]*network.EndpointSettings{
|
||||||
|
networkID: &network.EndpointSettings{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getActiveReplicaInstances(t *testing.T, cli *client.Client, qmReplicaIDs [3]string) (HAReplicaStatus, error) {
|
||||||
|
|
||||||
|
var actives []string
|
||||||
|
var replicas []string
|
||||||
|
|
||||||
|
for _, id := range qmReplicaIDs {
|
||||||
|
qmReplicaStatus := getQueueManagerStatus(t, cli, id, "QM1")
|
||||||
|
if qmReplicaStatus == "Running" {
|
||||||
|
actives = append(actives, id)
|
||||||
|
} else if qmReplicaStatus == "Replica" {
|
||||||
|
replicas = append(replicas, id)
|
||||||
|
} else {
|
||||||
|
err := fmt.Errorf("Expected status to be Running or Replica, got status: %s", qmReplicaStatus)
|
||||||
|
return HAReplicaStatus{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(actives) != 1 || len(replicas) != 2 {
|
||||||
|
err := fmt.Errorf("Expected 1 Active and 2 Replicas, got: %d Active and %d Replica", len(actives), len(replicas))
|
||||||
|
return HAReplicaStatus{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return HAReplicaStatus{actives[0], [2]string{replicas[0], replicas[1]}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForReadyHA(t *testing.T, cli *client.Client, qmReplicaIDs [3]string) {
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
for _, id := range qmReplicaIDs {
|
||||||
|
rc, _ := execContainer(t, cli, id, "", []string{"chkmqready"})
|
||||||
|
if rc == 0 {
|
||||||
|
t.Log("MQ is ready")
|
||||||
|
rc, _ := execContainer(t, cli, id, "", []string{"chkmqstarted"})
|
||||||
|
if rc == 0 {
|
||||||
|
t.Log("MQ has started")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("Timed out waiting for HA Queue Manager to become ready")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForFailoverHA(t *testing.T, cli *client.Client, replicas [2]string) {
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
for _, id := range replicas {
|
||||||
|
if status := getQueueManagerStatus(t, cli, id, "QM1"); status == "Running" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("Timed out waiting for Native HA Queue Manager to failover to an available replica")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -286,12 +286,12 @@ func TestQMRestart(t *testing.T) {
|
|||||||
|
|
||||||
// Restart just the QM (to simulate a lost connection)
|
// Restart just the QM (to simulate a lost connection)
|
||||||
t.Log("Stopping queue manager\n")
|
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 {
|
if rc != 0 {
|
||||||
t.Fatalf("Failed to stop the queue manager. rc=%d, err=%s", rc, out)
|
t.Fatalf("Failed to stop the queue manager. rc=%d, err=%s", rc, out)
|
||||||
}
|
}
|
||||||
t.Log("starting queue manager\n")
|
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 {
|
if rc != 0 {
|
||||||
t.Fatalf("Failed to start the queue manager. rc=%d, err=%s", rc, out)
|
t.Fatalf("Failed to start the queue manager. rc=%d, err=%s", rc, out)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# © Copyright IBM Corporation 2018, 2019
|
# © Copyright IBM Corporation 2018, 2021
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -15,22 +15,24 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# Application build environment (Maven)
|
# Application build environment (Maven)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
FROM docker.io/maven:3-ibmjava as builder
|
FROM registry.redhat.io/ubi8/openjdk-8 as builder
|
||||||
COPY pom.xml /usr/src/mymaven/
|
COPY pom.xml .
|
||||||
WORKDIR /usr/src/mymaven
|
#WORKDIR /usr/src/mymaven
|
||||||
# Download dependencies separately, so Docker caches them
|
# Download dependencies separately, so Docker caches them
|
||||||
RUN mvn dependency:go-offline install
|
RUN mvn dependency:go-offline install
|
||||||
# Copy source
|
# Copy source
|
||||||
COPY src /usr/src/mymaven/src
|
COPY src .
|
||||||
# Run the main build
|
# Run the main build
|
||||||
RUN mvn --offline install
|
RUN mvn --offline install
|
||||||
# Print a list of all the files (useful for debugging)
|
# Print a list of all the files (useful for debugging)
|
||||||
RUN find /usr/src/mymaven
|
RUN find .
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Application runtime (JRE only, no build environment)
|
# Application runtime (JRE only, no build environment)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
FROM docker.io/ibmjava:8-jre
|
# OpenJDK is not technically supported with the MQ client, but is good enough for these tests
|
||||||
COPY --from=builder /usr/src/mymaven/target/*.jar /opt/app/
|
FROM registry.redhat.io/ubi8/openjdk-8-runtime
|
||||||
COPY --from=builder /usr/src/mymaven/target/lib/*.jar /opt/app/
|
COPY --from=builder /home/jboss/target/*.jar /opt/app/
|
||||||
|
COPY --from=builder /home/jboss/target/lib/*.jar /opt/app/
|
||||||
|
USER 1001
|
||||||
ENTRYPOINT ["java", "-classpath", "/opt/app/*", "org.junit.platform.console.ConsoleLauncher", "-p", "com.ibm.mqcontainer.test", "--details", "verbose"]
|
ENTRYPOINT ["java", "-classpath", "/opt/app/*", "org.junit.platform.console.ConsoleLauncher", "-p", "com.ibm.mqcontainer.test", "--details", "verbose"]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
© Copyright IBM Corporation 2018
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -26,7 +26,7 @@ limitations under the License.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ibm.mq</groupId>
|
<groupId>com.ibm.mq</groupId>
|
||||||
<artifactId>com.ibm.mq.allclient</artifactId>
|
<artifactId>com.ibm.mq.allclient</artifactId>
|
||||||
<version>9.1.3.0</version>
|
<version>9.2.0.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -65,5 +65,9 @@ limitations under the License.
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
© Copyright IBM Corporation 2018
|
© Copyright IBM Corporation 2018, 2021
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -15,7 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
package com.ibm.mqcontainer.test;
|
package com.ibm.mqcontainer.test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -32,9 +32,12 @@ import javax.net.ssl.SSLContext;
|
|||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
|
import com.ibm.mq.MQException;
|
||||||
|
import com.ibm.mq.constants.MQConstants;
|
||||||
import com.ibm.mq.jms.MQConnectionFactory;
|
import com.ibm.mq.jms.MQConnectionFactory;
|
||||||
import com.ibm.mq.jms.MQQueue;
|
import com.ibm.mq.jms.MQQueue;
|
||||||
import com.ibm.msg.client.wmq.WMQConstants;
|
import com.ibm.msg.client.wmq.WMQConstants;
|
||||||
|
import com.ibm.msg.client.jms.DetailedJMSSecurityRuntimeException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@@ -57,27 +60,18 @@ class JMSTests {
|
|||||||
static SSLSocketFactory createSSLSocketFactory() throws IOException, GeneralSecurityException {
|
static SSLSocketFactory createSSLSocketFactory() throws IOException, GeneralSecurityException {
|
||||||
KeyStore ts=KeyStore.getInstance("jks");
|
KeyStore ts=KeyStore.getInstance("jks");
|
||||||
ts.load(new FileInputStream(TRUSTSTORE), PASSPHRASE.toCharArray());
|
ts.load(new FileInputStream(TRUSTSTORE), PASSPHRASE.toCharArray());
|
||||||
// KeyManagerFactory kmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
|
||||||
TrustManagerFactory tmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
TrustManagerFactory tmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
tmf.init(ts);
|
tmf.init(ts);
|
||||||
// tmf.init();
|
|
||||||
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
|
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
|
||||||
// Security.setProperty("crypto.policy", "unlimited");
|
|
||||||
ctx.init(null, tmf.getTrustManagers(), null);
|
ctx.init(null, tmf.getTrustManagers(), null);
|
||||||
return ctx.getSocketFactory();
|
return ctx.getSocketFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
static JMSContext create(String channel, String addr, String user, String password) throws JMSException, IOException, GeneralSecurityException {
|
static MQConnectionFactory createMQConnectionFactory(String channel, String addr) throws JMSException, IOException, GeneralSecurityException {
|
||||||
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as %s", channel, addr, user));
|
|
||||||
MQConnectionFactory factory = new MQConnectionFactory();
|
MQConnectionFactory factory = new MQConnectionFactory();
|
||||||
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
|
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
|
||||||
factory.setChannel(channel);
|
factory.setChannel(channel);
|
||||||
factory.setConnectionNameList(String.format("%s(1414)", addr));
|
factory.setConnectionNameList(String.format("%s(1414)", addr));
|
||||||
// If a password is set, make sure it gets sent to the queue manager for authentication
|
|
||||||
if (password != null) {
|
|
||||||
factory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
|
|
||||||
}
|
|
||||||
// factory.setClientReconnectOptions(WMQConstants.WMQ_CLIENT_RECONNECT);
|
|
||||||
if (TRUSTSTORE == null) {
|
if (TRUSTSTORE == null) {
|
||||||
LOGGER.info("Not using TLS");
|
LOGGER.info("Not using TLS");
|
||||||
}
|
}
|
||||||
@@ -94,12 +88,33 @@ class JMSTests {
|
|||||||
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
|
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Give up if unable to reconnect for 10 minutes
|
return factory;
|
||||||
// factory.setClientReconnectTimeout(600);
|
}
|
||||||
// LOGGER.info(String.format("user=%s pw=%s", user, password));
|
|
||||||
|
/**
|
||||||
|
* Create a JMSContext with the supplied user and password.
|
||||||
|
*/
|
||||||
|
static JMSContext create(String channel, String addr, String user, String password) throws JMSException, IOException, GeneralSecurityException {
|
||||||
|
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as %s", channel, addr, user));
|
||||||
|
MQConnectionFactory factory = createMQConnectionFactory(channel, addr);
|
||||||
|
// If a password is set, make sure it gets sent to the queue manager for authentication
|
||||||
|
if (password != null) {
|
||||||
|
factory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
|
||||||
|
}
|
||||||
|
LOGGER.info(String.format("CSP authentication: %s", factory.getBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP)));
|
||||||
return factory.createContext(user, password);
|
return factory.createContext(user, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a JMSContext with the default user identity (from the OS)
|
||||||
|
*/
|
||||||
|
static JMSContext create(String channel, String addr) throws JMSException, IOException, GeneralSecurityException {
|
||||||
|
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as OS user '%s'", channel, addr, System.getProperty("user.name")));
|
||||||
|
MQConnectionFactory factory = createMQConnectionFactory(channel, addr);
|
||||||
|
LOGGER.info(String.format("CSP authentication: %s", factory.getBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP)));
|
||||||
|
return factory.createContext();
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
private static void waitForQueueManager() {
|
private static void waitForQueueManager() {
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
@@ -116,28 +131,34 @@ class JMSTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void connect() throws Exception {
|
|
||||||
context = create(CHANNEL, ADDR, USER, PASSWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void succeedingTest(TestInfo t) throws JMSException {
|
void putGetTest(TestInfo t) throws Exception {
|
||||||
|
context = create(CHANNEL, ADDR, USER, PASSWORD);
|
||||||
Queue queue = new MQQueue("DEV.QUEUE.1");
|
Queue queue = new MQQueue("DEV.QUEUE.1");
|
||||||
context.createProducer().send(queue, t.getDisplayName());
|
context.createProducer().send(queue, t.getDisplayName());
|
||||||
Message m = context.createConsumer(queue).receive();
|
Message m = context.createConsumer(queue).receive();
|
||||||
assertNotNull(m.getBody(String.class));
|
assertNotNull(m.getBody(String.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
|
||||||
// void failingTest() {
|
|
||||||
// fail("a failing test");
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("for demonstration purposes")
|
void defaultIdentityTest(TestInfo t) throws Exception {
|
||||||
void skippedTest() {
|
LOGGER.info(String.format("Password='%s'", PASSWORD));
|
||||||
// not executed
|
try {
|
||||||
|
// Don't pass a user/password, which should cause the default identity to be used
|
||||||
|
context = create(CHANNEL, ADDR);
|
||||||
|
} catch (DetailedJMSSecurityRuntimeException ex) {
|
||||||
|
Throwable cause = ex.getCause();
|
||||||
|
assertNotNull(cause);
|
||||||
|
assertTrue(cause instanceof MQException);
|
||||||
|
assertEquals(MQConstants.MQRC_NOT_AUTHORIZED, ((MQException)cause).getReason());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The default developer config allows any user to appear as "app", and use a blank password. This is done with the MCAUSER on the channel.
|
||||||
|
// If this test is run on a queue manager without a password set, then it should be possible to connect without exception.
|
||||||
|
// If this test is run on a queue manager with a password set, then an exception should be thrown, because this test doesn't send a password.
|
||||||
|
if ((PASSWORD != null) && (PASSWORD != "")) {
|
||||||
|
fail("Exception not thrown");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
@@ -146,9 +167,4 @@ class JMSTests {
|
|||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
static void tearDownAll() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
205
travis-build-scripts/artifact-util.sh
Executable file
205
travis-build-scripts/artifact-util.sh
Executable file
@@ -0,0 +1,205 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
usage="
|
||||||
|
Usage: artifact-util.sh -c my-registry.com/artifacts/my-project/builds/123 -u me@org.com -p top-secret -f tagcache -l ./.tagcache --upload \"
|
||||||
|
|
||||||
|
Where:
|
||||||
|
-c - Full artifact destination hostname and path
|
||||||
|
-u - The username to access repository
|
||||||
|
-p - The password or api-key to access repository
|
||||||
|
-f - Name of the file in repository
|
||||||
|
-l - The path and name to the file whose contents is to be pushed or retrieved into
|
||||||
|
Then one action of either
|
||||||
|
--check - Check if the file exists
|
||||||
|
--upload - Upload the contents of a file [-l must be specified]
|
||||||
|
--get - Get a file and write to a local file [-l must be specified]
|
||||||
|
--delete - Delet the remote file from repository
|
||||||
|
"
|
||||||
|
|
||||||
|
GREEN="\033[32m"
|
||||||
|
RED="\033[31m"
|
||||||
|
|
||||||
|
END="\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
RIGHTARROW="\xE2\x96\xB6"
|
||||||
|
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"
|
||||||
|
|
||||||
|
USER=
|
||||||
|
CREDENTIAL=
|
||||||
|
FILE_NAME=
|
||||||
|
BUILD_ID=
|
||||||
|
REGISTRY_HOSTNAME=
|
||||||
|
FILE_LOCATION=
|
||||||
|
|
||||||
|
CHECK=false
|
||||||
|
UPLOAD=false
|
||||||
|
GET=false
|
||||||
|
DELETE=false
|
||||||
|
DELETE_NAMESPACE=false
|
||||||
|
num_commands_selected=0
|
||||||
|
while getopts "f:u:p:c:l:-:" flag
|
||||||
|
do
|
||||||
|
case "${flag}" in
|
||||||
|
f) FILE_NAME=${OPTARG};;
|
||||||
|
u) USER=${OPTARG};;
|
||||||
|
p) CREDENTIAL=${OPTARG};;
|
||||||
|
c) CACHE_PATH=${OPTARG};;
|
||||||
|
l) FILE_LOCATION=${OPTARG};;
|
||||||
|
-)
|
||||||
|
case "${OPTARG}" in
|
||||||
|
check)
|
||||||
|
CHECK=true
|
||||||
|
num_commands_selected=$((num_commands_selected+1))
|
||||||
|
;;
|
||||||
|
upload)
|
||||||
|
UPLOAD=true
|
||||||
|
num_commands_selected=$((num_commands_selected+1))
|
||||||
|
;;
|
||||||
|
get)
|
||||||
|
GET=true
|
||||||
|
num_commands_selected=$((num_commands_selected+1))
|
||||||
|
;;
|
||||||
|
delete)
|
||||||
|
DELETE=true
|
||||||
|
num_commands_selected=$((num_commands_selected+1))
|
||||||
|
;;
|
||||||
|
delete-namespace)
|
||||||
|
DELETE_NAMESPACE=true
|
||||||
|
num_commands_selected=$((num_commands_selected+1))
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
|
||||||
|
echo "Unknown option --${OPTARG}" >&2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $num_commands_selected == 0 || $num_commands_selected -gt 1 ]]; then
|
||||||
|
printf "${REDCROSS} ${ERROR}Too many actions specified. Should be one of ${END}--check${ERROR},${END} --get${ERROR},${END} --upload${ERROR} or${END} --delete${ERROR}!${END}\n"
|
||||||
|
printf $SPACER
|
||||||
|
printf "${ERROR}$usage${END}\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DELETE_NAMESPACE" != "true" ]; then
|
||||||
|
if [[ -z $CACHE_PATH|| -z $USER || -z $CREDENTIAL || -z $FILE_NAME ]] ; then
|
||||||
|
printf "${REDCROSS} ${ERROR}Missing parameter!${END}\n"
|
||||||
|
printf "Cache Path:"$CACHE_PATH"\n"
|
||||||
|
printf "File name:"$FILE_NAME"\n"
|
||||||
|
printf "User":$USER"\n"
|
||||||
|
printf $SPACER
|
||||||
|
printf "${ERROR}$usage${END}\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
REMOTE_PATH="https://${CACHE_PATH}/$TRAVIS_BUILD_ID"
|
||||||
|
|
||||||
|
if [ "$CHECK" == "true" ]; then
|
||||||
|
printf "${GREENRIGHTARROW} Checking to see if file ${FILE_NAME} exists in repository ${REMOTE_PATH}\n"
|
||||||
|
FILE_FOUND=`curl -u ${USER}:${CREDENTIAL} -X GET "${REMOTE_PATH}/${FILE_NAME}" -o /dev/null -w "%{http_code}" -s`
|
||||||
|
if [ "$FILE_FOUND" != "200" ]; then
|
||||||
|
printf "${REDCROSS} File ${FILE_NAME} was not found\n"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} File ${FILE_NAME} was found\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$UPLOAD" == "true" ]; then
|
||||||
|
printf "${GREENRIGHTARROW} Attempting to upload the file ${FILE_NAME} to repository ${REMOTE_PATH}\n"
|
||||||
|
if [[ -z $FILE_LOCATION ]]; then
|
||||||
|
printf "${REDCROSS} Location for ${FILE_NAME} was not supplied please do so\n"
|
||||||
|
printf $SPACER
|
||||||
|
printf "${ERROR}$usage${END}\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$FILE_LOCATION" ]; then
|
||||||
|
printf "${REDCROSS} Location supplied ${FILE_LOCATION } for file ${FILE_NAME} did not resolve to a file with contents to upload\n"
|
||||||
|
printf $SPACER
|
||||||
|
printf "${ERROR}$usage${END}\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
curl -u ${USER}:${CREDENTIAL} -X PUT "$REMOTE_PATH/${FILE_NAME}" -T ${FILE_LOCATION}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GET" == "true" ]; then
|
||||||
|
printf "${GREENRIGHTARROW} Attempting to download file ${FILE_NAME} from repository ${REMOTE_PATH} to ${FILE_LOCATION}\n"
|
||||||
|
if [[ -z $FILE_LOCATION ]]; then
|
||||||
|
printf "${REDCROSS} Location for ${FILE_NAME} was not supplied please do so\n"
|
||||||
|
printf $SPACER
|
||||||
|
printf "${ERROR}$usage${END}\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
curl -u ${USER}:${CREDENTIAL} "$REMOTE_PATH/${FILE_NAME}" -o ${FILE_LOCATION} -s
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
printf "${REDCROSS} Failed download\n"
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} File ${FILE_NAME} was downloaded to ${FILE_LOCATION}\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DELETE" == "true" ]; then
|
||||||
|
printf "${GREENRIGHTARROW} Checking to see if file ${FILE_NAME} exists in repository ${REMOTE_PATH} before delete\n"
|
||||||
|
FILE_FOUND=`curl -u ${USER}:${CREDENTIAL} -X GET "${REMOTE_PATH}/${FILE_NAME}" -o /dev/null -w "%{http_code}" -s`
|
||||||
|
if [ "$FILE_FOUND" != "200" ]; then
|
||||||
|
printf "${REDCROSS} File ${FILE_NAME} was not found to delete\n"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} File ${FILE_NAME} was found\n"
|
||||||
|
printf "${GREENRIGHTARROW} Attempting the delete of ${REMOTE_PATH}/${FILE_NAME}"
|
||||||
|
curl -u ${USER}:${CREDENTIAL} -X DELETE "${REMOTE_PATH}/${FILE_NAME}" -s
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
printf "${REDCROSS} Failed delete\n"
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} File ${FILE_NAME} was deleted from "${REMOTE_PATH}"\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DELETE_NAMESPACE" == "true" ]; then
|
||||||
|
printf "${GREENRIGHTARROW} Checking to see if repository ${REMOTE_PATH} exists before delete\n"
|
||||||
|
DIR_FOUND=`curl -u ${USER}:${CREDENTIAL} -X GET "${REMOTE_PATH}" -o /dev/null -w "%{http_code}" -s`
|
||||||
|
if [ "$DIR_FOUND" != "200" ]; then
|
||||||
|
printf "${REDCROSS} Namespace ${REMOTE_PATH} was not found to delete\n"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} Namespace ${REMOTE_PATH} was found\n"
|
||||||
|
printf "${GREENRIGHTARROW} Attempting the delete of ${REMOTE_PATH}"
|
||||||
|
curl -u ${USER}:${CREDENTIAL} -X DELETE "${REMOTE_PATH}" -s
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
printf "${REDCROSS} Failed delete\n"
|
||||||
|
else
|
||||||
|
printf "${GREENTICK} Namespace ${REMOTE_PATH} deleted \n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# © Copyright IBM Corporation 2019
|
# © Copyright IBM Corporation 2019, 2020
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,40 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo 'Building Developer JMS test image...' && echo -en 'travis_fold:start:build-devjmstest\\r'
|
if [ "$TRAVIS_BRANCH" = "$MAIN_BRANCH" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
||||||
make build-devjmstest
|
echo 'Retrieving global tagcache' && echo -en 'travis_fold:start:tag-cache-retrieve\\r'
|
||||||
echo -en 'travis_fold:end:build-devjmstest\\r'
|
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} -l ./.tagcache --check
|
||||||
echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
|
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} -l ./.tagcache --get
|
||||||
make build-devserver
|
echo -en 'travis_fold:end:tag-cache-retrieve\\r'
|
||||||
echo -en 'travis_fold:end:build-devserver\\r'
|
fi
|
||||||
if [ "$BUILD_ALL" = true ] ; then
|
if [ -z "$BUILD_INTERNAL_LEVEL" ] ; then
|
||||||
|
if [ "$LTS" != true ] ; then
|
||||||
|
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'
|
||||||
|
fi
|
||||||
|
if [ "$BUILD_ALL" = true ] || [ "$LTS" = 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
|
||||||
|
else
|
||||||
|
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'
|
||||||
|
|
||||||
|
if [[ "$BUILD_INTERNAL_LEVEL" == *".DE"* ]]; then
|
||||||
|
echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
|
||||||
|
make build-devserver
|
||||||
|
echo -en 'travis_fold:end:build-devserver\\r'
|
||||||
|
else
|
||||||
echo 'Building Production image...' && echo -en 'travis_fold:start:build-advancedserver\\r'
|
echo 'Building Production image...' && echo -en 'travis_fold:start:build-advancedserver\\r'
|
||||||
make build-advancedserver
|
make build-advancedserver
|
||||||
echo -en 'travis_fold:end:build-advancedserver\\r'
|
echo -en 'travis_fold:end:build-advancedserver\\r'
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
19
vendor/github.com/ibm-messaging/mq-golang/Dockerfile-build-samples → travis-build-scripts/cleanup-cache.sh
Normal file → Executable file
19
vendor/github.com/ibm-messaging/mq-golang/Dockerfile-build-samples → travis-build-scripts/cleanup-cache.sh
Normal file → Executable file
@@ -1,4 +1,6 @@
|
|||||||
# © Copyright IBM Corporation 2018
|
#!/bin/bash
|
||||||
|
|
||||||
|
# © Copyright IBM Corporation 2020
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,15 +14,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
ARG BASE_IMAGE=mq-golang-build:9.0.5.0-x86_64-ubuntu-16.04
|
echo 'Cleaning up remote cache' && echo -en 'travis_fold:start:cleanup\\r'
|
||||||
|
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} --delete
|
||||||
FROM $BASE_IMAGE
|
echo -en 'travis_fold:end:cleanup\\r'
|
||||||
|
|
||||||
RUN mkdir -p "$GOPATH/src/github.com/ibm-messaging/mq-golang/samples"
|
|
||||||
WORKDIR $GOPATH/src/github.com/ibm-messaging/mq-golang/samples
|
|
||||||
|
|
||||||
COPY ./samples/clientconn clientconn
|
|
||||||
COPY ./samples/mqitest mqitest
|
|
||||||
|
|
||||||
RUN go install ./clientconn \
|
|
||||||
&& go install ./mqitest
|
|
||||||
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
|
||||||
|
MANIFEST_DIGEST=$(docker manifest push --purge $REGISTRY/$NAMESPACE/$IMAGE:$TAG)
|
||||||
|
|
||||||
|
echo $MANIFEST_DIGEST
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
|
# © Copyright IBM Corporation 2020
|
||||||
#
|
#
|
||||||
# Copyright 2018 The Prometheus Authors
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
@@ -13,17 +14,11 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
check_license() {
|
set -e
|
||||||
local file=""
|
|
||||||
for file in $(find . -type f -iname '*.go' ! -path './vendor/*'); do
|
|
||||||
head -n3 "${file}" | grep -Eq "(Copyright|generated|GENERATED)" || echo " ${file}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
licRes=$(check_license)
|
echo 'Cacheing MQ tag...' && echo -en 'travis_fold:start:build-cache-mq-tag\\r'
|
||||||
|
make cache-mq-tag
|
||||||
if [ -n "${licRes}" ]; then
|
echo -en 'travis_fold:end:cache-mq-tag\\r'
|
||||||
echo "license header checking failed:"
|
echo 'Caching tagcache for future stages' && echo -en 'travis_fold:start:tag-cache\\r'
|
||||||
echo "${licRes}"
|
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} -l ./.tagcache --upload
|
||||||
exit 255
|
echo -en 'travis_fold:end:tag-cache\\r'
|
||||||
fi
|
|
||||||
52
travis-build-scripts/install-credential-helper.sh
Executable file
52
travis-build-scripts/install-credential-helper.sh
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
echo "default-cache-ttl 1200" > /home/travis/.gnupg/gpg-agent.conf
|
||||||
|
gpg-connect-agent reloadagent /bye
|
||||||
|
|
||||||
|
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
|
||||||
|
gpg2 --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
|
||||||
|
Passphrase: $REGISTRY_PASS
|
||||||
|
%commit
|
||||||
|
%echo done
|
||||||
|
EOF
|
||||||
|
key=$(gpg2 --list-secret-keys | grep uid -B 1 | head -n 1 | sed 's/^ *//g')
|
||||||
|
pass init $key
|
||||||
|
pass insert docker-credential-helpers/docker-pass-initialized-check <<-EOF
|
||||||
|
pass is initialized
|
||||||
|
pass is initialized
|
||||||
|
EOF
|
||||||
|
gpg2 --passphrase $REGISTRY_PASS --pinentry-mode=loopback --output doc --decrypt ~/.password-store/docker-credential-helpers/docker-pass-initialized-check.gpg
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# © Copyright IBM Corporation 2019
|
# © Copyright IBM Corporation 2019, 2020
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -21,7 +21,7 @@ if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -z $2 ]; then
|
if [ ! -z $2 ]; then
|
||||||
export ARCH=$2
|
export ARCH=$2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -32,9 +32,11 @@ function push_developer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function push_production {
|
function push_production {
|
||||||
echo 'Pushing Production image...' && echo -en 'travis_fold:start:push-advancedserver\\r'
|
if [[ "$ARCH" = "amd64" || "$ARCH" = "s390x" ]] ; then
|
||||||
make push-advancedserver
|
echo 'Pushing Production image...' && echo -en 'travis_fold:start:push-advancedserver\\r'
|
||||||
echo -en 'travis_fold:end:push-advancedserver\\r'
|
make push-advancedserver
|
||||||
|
echo -en 'travis_fold:end:push-advancedserver\\r'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# call relevant push function
|
# call relevant push function
|
||||||
@@ -48,7 +50,7 @@ if [ ! -z $1 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
echo "ERROR: Type ( developer | production ) must be passed to push.sh"
|
echo "ERROR: Type ( developer | production ) must be passed to push.sh"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# © Copyright IBM Corporation 2019
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# staging or production
|
|
||||||
TYPE=""
|
|
||||||
MANIFEST_FILE=manifest-9.1.4.yaml
|
|
||||||
|
|
||||||
# set type of release
|
|
||||||
if [ ! -z $1 ]; then
|
|
||||||
case "$1" in
|
|
||||||
staging) TYPE=$1
|
|
||||||
;;
|
|
||||||
production) TYPE=$1
|
|
||||||
;;
|
|
||||||
*) echo "ERROR: Release type ( staging | production ) must passed to release.sh"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
echo "ERROR: Release type ( staging | production ) must passed to release.sh"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
## Pull all images from default repository
|
|
||||||
ARCH=amd64 make pull-devserver
|
|
||||||
ARCH=ppc64le make pull-devserver
|
|
||||||
ARCH=s390x make pull-devserver
|
|
||||||
|
|
||||||
ARCH=amd64 make pull-advancedserver
|
|
||||||
ARCH=ppc64le make pull-advancedserver
|
|
||||||
ARCH=s390x make pull-advancedserver
|
|
||||||
|
|
||||||
|
|
||||||
function set_staging_registry {
|
|
||||||
export MQ_DELIVERY_REGISTRY_HOSTNAME=$MQ_STAGING_REGISTRY
|
|
||||||
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
|
|
||||||
export MQ_DELIVERY_REGISTRY_USER=$MQ_STAGING_REGISTRY_USER
|
|
||||||
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_STAGING_REGISTRY_CREDENTIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_docker_hub {
|
|
||||||
export MQ_DELIVERY_REGISTRY_HOSTNAME=ibmcom
|
|
||||||
export MQ_DELIVERY_REGISTRY_NAMESPACE=mq
|
|
||||||
export MQ_DELIVERY_REGISTRY_USER=$MQ_DOCKERHUB_REGISTRY_USER
|
|
||||||
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_DOCKERHUB_REGISTRY_CREDENTIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_docker_store {
|
|
||||||
export MQ_DELIVERY_REGISTRY_HOSTNAME=ibmcorp
|
|
||||||
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
|
|
||||||
export MQ_DELIVERY_REGISTRY_USER=$MQ_DOCKERHUB_REGISTRY_USER
|
|
||||||
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_DOCKERHUB_REGISTRY_CREDENTIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_production_registry {
|
|
||||||
export MQ_DELIVERY_REGISTRY_HOSTNAME=$MQ_PRODUCTION_REGISTRY
|
|
||||||
export MQ_DELIVERY_REGISTRY_NAMESPACE=""
|
|
||||||
export MQ_DELIVERY_REGISTRY_USER=$MQ_PRODUCTION_REGISTRY_USER
|
|
||||||
export MQ_DELIVERY_REGISTRY_CREDENTIAL=$MQ_PRODUCTION_REGISTRY_CREDENTIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$TYPE" = "staging" ]; then
|
|
||||||
|
|
||||||
set_staging_registry
|
|
||||||
|
|
||||||
# push production images to staging registy
|
|
||||||
./travis-build-scripts/push.sh production amd64
|
|
||||||
./travis-build-scripts/push.sh production ppc64le
|
|
||||||
./travis-build-scripts/push.sh production s390x
|
|
||||||
|
|
||||||
elif [ "$TYPE" = "production" ]; then
|
|
||||||
|
|
||||||
# pull production images from staging
|
|
||||||
set_staging_registry
|
|
||||||
|
|
||||||
ARCH=amd64 make pull-advancedserver
|
|
||||||
ARCH=ppc64le make pull-advancedserver
|
|
||||||
ARCH=s390x make pull-advancedserver
|
|
||||||
|
|
||||||
# release developer images with fat manifests
|
|
||||||
set_docker_hub
|
|
||||||
|
|
||||||
./travis-build-scripts/push.sh developer amd64
|
|
||||||
./travis-build-scripts/push.sh developer ppc64le
|
|
||||||
./travis-build-scripts/push.sh developer s390x
|
|
||||||
|
|
||||||
docker login --username $MQ_DOCKERHUB_REGISTRY_USER --password $MQ_DOCKERHUB_REGISTRY_CREDENTIAL
|
|
||||||
./manifest-tool-linux-amd64 push from-spec manifests/dockerhub/$MANIFEST_FILE
|
|
||||||
./manifest-tool-linux-amd64 push from-spec manifests/dockerhub/manifest-latest.yaml
|
|
||||||
|
|
||||||
set_docker_store
|
|
||||||
|
|
||||||
./travis-build-scripts/push.sh developer amd64
|
|
||||||
./travis-build-scripts/push.sh developer ppc64le
|
|
||||||
./travis-build-scripts/push.sh developer s390x
|
|
||||||
|
|
||||||
docker login --username $MQ_DOCKERHUB_REGISTRY_USER --password $MQ_DOCKERHUB_REGISTRY_CREDENTIAL
|
|
||||||
./manifest-tool-linux-amd64 push from-spec manifests/dockerstore/$MANIFEST_FILE
|
|
||||||
|
|
||||||
# release production image
|
|
||||||
set_production_registry
|
|
||||||
|
|
||||||
./travis-build-scripts/push.sh production amd64
|
|
||||||
./travis-build-scripts/push.sh production ppc64le
|
|
||||||
./travis-build-scripts/push.sh production s390x
|
|
||||||
fi
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user