Merge pull request #15 from arthurbarr/master
Updates ready for MQ V9.0.4
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
charts
|
||||
cmd
|
||||
downloads
|
||||
pkg
|
||||
test
|
||||
vendor
|
||||
|
||||
@@ -8,6 +8,10 @@ services:
|
||||
- docker
|
||||
|
||||
before_install:
|
||||
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y install docker-ce
|
||||
- curl https://glide.sh/get | sh
|
||||
- curl -LO https://github.com/golang/dep/releases/download/v0.3.0/dep-linux-amd64.zip
|
||||
- unzip dep-linux-amd64.zip
|
||||
|
||||
13
CHANGELOG.md
Normal file
13
CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Change log
|
||||
|
||||
## 9.0.4 (2017-11-01)
|
||||
* Updated to MQ version 9.0.4.0
|
||||
* Updated to Go version 9
|
||||
* Removed packages `curl`, `ca-certificates`, and their dependencies, which were only used at build time
|
||||
* Improved logging
|
||||
* Helm charts now work on Kubernetes V1.6
|
||||
* Production Helm chart now includes a default image repository and tag
|
||||
* Updated to use multi-stage Docker build, so that Go code is built inside a container
|
||||
|
||||
## 9.0.3 (2017-10-17)
|
||||
* Initial version
|
||||
@@ -1,50 +0,0 @@
|
||||
# © Copyright IBM Corporation 2015, 2017
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM ubuntu:16.04
|
||||
|
||||
LABEL "ProductID"="4486e8c4cc9146fd9b3ce1f14a2dfc5b" \
|
||||
"ProductName"="IBM MQ Advanced for Developers" \
|
||||
"ProductVersion"="9.0.3"
|
||||
|
||||
# The URL to download the MQ installer from in tar.gz format
|
||||
# This assumes an archive containing the MQ Debian (.deb) install packages
|
||||
ARG MQ_URL=https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/mqadv_dev903_ubuntu_x86-64.tar.gz
|
||||
|
||||
# The MQ packages to install
|
||||
ARG MQ_PACKAGES="ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-ams"
|
||||
|
||||
COPY install-mq.sh /usr/local/bin/
|
||||
RUN chmod u+x /usr/local/bin/install-mq.sh \
|
||||
# To avoid a "text file busy" error here we sleep before installing.
|
||||
&& sleep 1 && install-mq.sh
|
||||
|
||||
COPY build/runmqserver /usr/local/bin/
|
||||
COPY build/chkmq* /usr/local/bin/
|
||||
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
|
||||
|
||||
# MQ default developer config
|
||||
COPY dev/mq-dev-config /etc/mqm/mq-dev-config
|
||||
COPY dev/mq-dev-config.sh /usr/local/bin/
|
||||
COPY dev/admin.json /etc/mqm/
|
||||
|
||||
RUN chmod +x /usr/local/bin/runmqserver \
|
||||
&& chmod +x /usr/local/bin/chk*
|
||||
|
||||
# Always use port 1414
|
||||
EXPOSE 1414
|
||||
|
||||
ENV LANG=en_US.UTF-8 AMQ_DIAGNOSTIC_MSG_SEVERITY=1
|
||||
|
||||
ENTRYPOINT ["runmqserver"]
|
||||
@@ -12,11 +12,24 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM ubuntu:16.04
|
||||
# Build stage to build Go code
|
||||
FROM golang:1.9 as builder
|
||||
WORKDIR /go/src/github.com/ibm-messaging/mq-container/
|
||||
COPY cmd/ ./cmd
|
||||
COPY pkg/ ./pkg
|
||||
COPY vendor/ ./vendor
|
||||
RUN go build ./cmd/runmqserver/
|
||||
RUN go build ./cmd/chkmqready/
|
||||
RUN go build ./cmd/chkmqhealthy/
|
||||
|
||||
ARG IBM_PRODUCT_ID
|
||||
ARG IBM_PRODUCT_NAME
|
||||
ARG IBM_PRODUCT_VERSION
|
||||
# Build stage to run Go unit tests
|
||||
FROM golang:1.9 as tester
|
||||
COPY pkg/ ./pkg
|
||||
RUN cd pkg/name && go test
|
||||
RUN cd pkg/linux/capabilities && go test
|
||||
|
||||
# Main build stage, to build MQ image
|
||||
FROM ubuntu:16.04
|
||||
|
||||
# The URL to download the MQ installer from in tar.gz format
|
||||
# This assumes an archive containing the MQ Debian (.deb) install packages
|
||||
@@ -25,17 +38,15 @@ ARG MQ_URL
|
||||
# The MQ packages to install
|
||||
ARG MQ_PACKAGES="ibmmq-server ibmmq-java ibmmq-jre ibmmq-gskit ibmmq-msg-.* ibmmq-samples ibmmq-ams"
|
||||
|
||||
LABEL "ProductID"=$IBM_PRODUCT_ID \
|
||||
"ProductName"=$IBM_PRODUCT_NAME \
|
||||
"ProductVersion"=$IBM_PRODUCT_VERSION
|
||||
|
||||
COPY install-mq.sh /usr/local/bin/
|
||||
RUN chmod u+x /usr/local/bin/install-mq.sh \
|
||||
# To avoid a "text file busy" error here we sleep before installing.
|
||||
&& sleep 1 && install-mq.sh
|
||||
|
||||
COPY build/runmqserver /usr/local/bin/
|
||||
COPY build/chkmq* /usr/local/bin/
|
||||
# Install MQ. To avoid a "text file busy" error here, we sleep before installing.
|
||||
RUN chmod u+x /usr/local/bin/install-mq.sh \
|
||||
&& sleep 1 \
|
||||
&& install-mq.sh
|
||||
|
||||
COPY --from=builder /go/src/github.com/ibm-messaging/mq-container/runmqserver /usr/local/bin/
|
||||
COPY --from=builder /go/src/github.com/ibm-messaging/mq-container/chkmq* /usr/local/bin/
|
||||
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
|
||||
|
||||
RUN chmod +x /usr/local/bin/runmqserver \
|
||||
|
||||
72
Makefile
72
Makefile
@@ -13,9 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
BUILD_SERVER_CONTAINER=build-server
|
||||
# Set architecture for Go code. Don't set GOOS globally, so that tests can be run locally
|
||||
export GOARCH ?= amd64
|
||||
# Don't set GOOS globally, so that tests can be run locally
|
||||
DOCKER_TAG_ARCH ?= x86_64
|
||||
# By default, all Docker client commands are run inside a Docker container.
|
||||
# This means that newer features of the client can be used, even with an older daemon.
|
||||
DOCKER ?= docker run --tty --interactive --rm --volume /var/run/docker.sock:/var/run/docker.sock --volume "$(CURDIR)":/var/src --workdir /var/src docker:stable docker
|
||||
DOCKER_TAG ?= latest-$(DOCKER_TAG_ARCH)
|
||||
DOCKER_REPO_DEVSERVER ?= mq-devserver
|
||||
DOCKER_REPO_ADVANCEDSERVER ?= mq-advancedserver
|
||||
@@ -60,43 +63,28 @@ deps:
|
||||
cd test/docker && dep ensure -vendor-only
|
||||
cd test/kubernetes && dep ensure -vendor-only
|
||||
|
||||
build/runmqserver:
|
||||
mkdir -p build
|
||||
cd build; GOOS=linux go build ../cmd/runmqserver/
|
||||
|
||||
build/chkmqready:
|
||||
mkdir -p build
|
||||
cd build; GOOS=linux go build ../cmd/chkmqready/
|
||||
|
||||
build/chkmqhealthy:
|
||||
mkdir -p build
|
||||
cd build; GOOS=linux go build ../cmd/chkmqhealthy/
|
||||
|
||||
.PHONY: build
|
||||
build: build/runmqserver build/chkmqready build/chkmqhealthy
|
||||
|
||||
.PHONY: build-cov
|
||||
build-cov:
|
||||
mkdir -p build
|
||||
cd build; go test -c -covermode=count ../cmd/runmqserver
|
||||
|
||||
.PHONY: test-advancedserver
|
||||
test-advancedserver: build
|
||||
test-advancedserver:
|
||||
cd pkg/name && go test
|
||||
cd test/docker && TEST_IMAGE=$(DOCKER_FULL_ADVANCEDSERVER) go test $(TEST_OPTS_DOCKER)
|
||||
|
||||
.PHONY: test-devserver
|
||||
test-devserver: build
|
||||
test-devserver:
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Test $(DOCKER_FULL_DEVSERVER)"$(END)))
|
||||
cd pkg/name && go test
|
||||
cd test/docker && TEST_IMAGE=$(DOCKER_FULL_DEVSERVER) go test
|
||||
|
||||
.PHONY: test-kubernetes-devserver
|
||||
test-kubernetes-devserver: build
|
||||
test-kubernetes-devserver:
|
||||
$(call test-kubernetes,$(DOCKER_REPO_DEVSERVER),$(DOCKER_TAG),"../../charts/ibm-mqadvanced-server-dev")
|
||||
|
||||
.PHONY: test-kubernetes-advancedserver
|
||||
test-kubernetes-advancedserver: build
|
||||
test-kubernetes-advancedserver:
|
||||
$(call test-kubernetes,$(DOCKER_REPO_ADVANCEDSERVER),$(DOCKER_TAG),"../../charts/ibm-mqadvanced-server-prod")
|
||||
|
||||
define test-kubernetes
|
||||
@@ -106,9 +94,9 @@ endef
|
||||
|
||||
define docker-build-mq
|
||||
# Create a temporary network to use for the build
|
||||
docker network create build
|
||||
$(DOCKER) network create build
|
||||
# Start a web server to host the MQ downloadable (tar.gz) file
|
||||
docker run \
|
||||
$(DOCKER) run \
|
||||
--rm \
|
||||
--name $(BUILD_SERVER_CONTAINER) \
|
||||
--network build \
|
||||
@@ -117,48 +105,58 @@ define docker-build-mq
|
||||
--detach \
|
||||
nginx:alpine
|
||||
# Build the new image
|
||||
docker build \
|
||||
$(DOCKER) build \
|
||||
--pull \
|
||||
--tag $1 \
|
||||
--file $2 \
|
||||
--network build \
|
||||
--build-arg MQ_URL=http://build:80/$3 \
|
||||
--build-arg IBM_PRODUCT_ID=$4 \
|
||||
--build-arg IBM_PRODUCT_NAME=$5 \
|
||||
--build-arg IBM_PRODUCT_VERSION=$6 \
|
||||
--label IBM_PRODUCT_ID=$4 \
|
||||
--label IBM_PRODUCT_NAME=$5 \
|
||||
--label IBM_PRODUCT_VERSION=$6 \
|
||||
.
|
||||
# Stop the web server (will also remove the container)
|
||||
docker kill $(BUILD_SERVER_CONTAINER)
|
||||
$(DOCKER) kill $(BUILD_SERVER_CONTAINER)
|
||||
# Delete the temporary network
|
||||
docker network rm build
|
||||
$(DOCKER) network rm build
|
||||
endef
|
||||
|
||||
.PHONY: build-advancedserver
|
||||
build-advancedserver: build downloads/CNJR7ML.tar.gz
|
||||
# .PHONY: build-advancedserver-903
|
||||
# build-advancedserver-903: build downloads/CNJR7ML.tar.gz
|
||||
# $(info $(SPACER)$(shell printf $(TITLE)"Build $(DOCKER_FULL_ADVANCEDSERVER)"$(END)))
|
||||
# $(call docker-build-mq,$(DOCKER_FULL_ADVANCEDSERVER),Dockerfile-server,CNJR7ML.tar.gz,"4486e8c4cc9146fd9b3ce1f14a2dfc5b","IBM MQ Advanced","9.0.3")
|
||||
# $(DOCKER) tag $(DOCKER_FULL_ADVANCEDSERVER) $(DOCKER_REPO_ADVANCEDSERVER):9.0.3-$(DOCKER_TAG_ARCH)
|
||||
|
||||
.PHONY: build-advancedserver-904
|
||||
build-advancedserver-904: downloads/CNLE4ML.tar.gz
|
||||
$(info $(SPACER)$(shell printf $(TITLE)"Build $(DOCKER_FULL_ADVANCEDSERVER)"$(END)))
|
||||
$(call docker-build-mq,$(DOCKER_FULL_ADVANCEDSERVER),Dockerfile-server,CNJR7ML.tar.gz,"4486e8c4cc9146fd9b3ce1f14a2dfc5b","IBM MQ Advanced","9.0.3")
|
||||
docker tag $(DOCKER_FULL_ADVANCEDSERVER) $(DOCKER_REPO_ADVANCEDSERVER):9.0.3-$(DOCKER_TAG_ARCH)
|
||||
$(call docker-build-mq,$(DOCKER_FULL_ADVANCEDSERVER),Dockerfile-server,CNLE4ML.tar.gz,"4486e8c4cc9146fd9b3ce1f14a2dfc5b","IBM MQ Advanced","9.0.4")
|
||||
$(DOCKER) tag $(DOCKER_FULL_ADVANCEDSERVER) $(DOCKER_REPO_ADVANCEDSERVER):9.0.4-$(DOCKER_TAG_ARCH)
|
||||
|
||||
.PHONY: build-advancedserver
|
||||
build-advancedserver: build-advancedserver-904
|
||||
|
||||
.PHONY: build-devserver
|
||||
build-devserver: build downloads/mqadv_dev903_ubuntu_x86-64.tar.gz
|
||||
build-devserver: downloads/mqadv_dev903_ubuntu_x86-64.tar.gz
|
||||
$(info $(shell printf $(TITLE)"Build $(DOCKER_FULL_DEVSERVER)"$(END)))
|
||||
$(call docker-build-mq,$(DOCKER_FULL_DEVSERVER),Dockerfile-server,mqadv_dev903_ubuntu_x86-64.tar.gz,"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers (Non-Warranted)","9.0.3")
|
||||
docker tag $(DOCKER_FULL_DEVSERVER) $(DOCKER_REPO_DEVSERVER):9.0.3-$(DOCKER_TAG_ARCH)
|
||||
$(DOCKER) tag $(DOCKER_FULL_DEVSERVER) $(DOCKER_REPO_DEVSERVER):9.0.3-$(DOCKER_TAG_ARCH)
|
||||
|
||||
# .PHONY: build-server
|
||||
# build-server: build downloads/CNJR7ML.tar.gz
|
||||
# $(call docker-build-mq,mq-server:latest-$(DOCKER_TAG_ARCH),Dockerfile-server,"79afd716d55b4f149a87bec52c9dc1aa","IBM MQ","9.0.3")
|
||||
# docker tag mq-server:latest-$(DOCKER_TAG_ARCH) mq-server:9.0.3-$(DOCKER_TAG_ARCH)
|
||||
# $(DOCKER) tag mq-server:latest-$(DOCKER_TAG_ARCH) mq-server:9.0.3-$(DOCKER_TAG_ARCH)
|
||||
|
||||
.PHONY: build-advancedserver-cover
|
||||
build-advancedserver-cover: build-advanced-server build-cov
|
||||
docker build -t mq-advancedserver:cover -f Dockerfile-server.cover .
|
||||
$(DOCKER) build -t mq-advancedserver:cover -f Dockerfile-server.cover .
|
||||
|
||||
# .PHONY: build-web
|
||||
# build-web: build downloads/CNJR7ML.tar.gz
|
||||
# $(call docker-build-mq,mq-web:latest-$(DOCKER_TAG_ARCH),Dockerfile-mq-web)
|
||||
|
||||
.PHONY: build-explorer
|
||||
build-explorer: build downloads/mqadv_dev903_ubuntu_x86-64.tar.gz
|
||||
build-explorer: downloads/mqadv_dev903_ubuntu_x86-64.tar.gz
|
||||
$(call docker-build-mq,mq-explorer:latest-$(DOCKER_TAG_ARCH),incubating/mq-explorer/Dockerfile-mq-explorer,mqadv_dev903_ubuntu_x86-64.tar.gz,"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers (Non-Warranted)","9.0.3")
|
||||
|
||||
include formatting.mk
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
apiVersion: v1
|
||||
description: IBM MQ queue manager
|
||||
name: ibm-mqadvanced-server-dev
|
||||
version: 1.0.1
|
||||
version: 1.0.2
|
||||
icon: https://developer.ibm.com/messaging/wp-content/uploads/sites/18/2017/07/IBM-MQ-Square-200.png
|
||||
tillerVersion: ">=2.4.0"
|
||||
|
||||
@@ -10,7 +10,7 @@ This chart deploys a single IBM MQ Advanced for Developers server (queue manager
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.7 or greater, with beta APIs enabled
|
||||
- Kubernetes 1.6 or greater, with beta APIs enabled
|
||||
- If persistence is enabled (see [configuration](#configuration)), then you either need to create a PersistentVolume, or specify a Storage Class if classes are defined in your cluster.
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
@@ -24,8 +24,10 @@ metadata:
|
||||
spec:
|
||||
serviceName: {{ .Values.service.name }}
|
||||
replicas: 1
|
||||
{{- if and (ge (.Capabilities.KubeVersion.Major | int) 1) (ge (.Capabilities.KubeVersion.Minor | int) 7) }}
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
apiVersion: v1
|
||||
description: IBM MQ queue manager
|
||||
name: ibm-mqadvanced-server-prod
|
||||
version: 1.0.1
|
||||
version: 1.0.2
|
||||
icon: https://developer.ibm.com/messaging/wp-content/uploads/sites/18/2017/07/IBM-MQ-Square-200.png
|
||||
tillerVersion: ">=2.4.0"
|
||||
|
||||
@@ -10,7 +10,7 @@ This chart deploys a single IBM MQ Advanced server (queue manager) into an IBM C
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.7 or greater, with beta APIs enabled
|
||||
- Kubernetes 1.6 or greater, with beta APIs enabled
|
||||
- If persistence is enabled (see [configuration](#configuration)), then you either need to create a PersistentVolume, or specify a Storage Class if classes are defined in your cluster.
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
@@ -24,8 +24,10 @@ metadata:
|
||||
spec:
|
||||
serviceName: {{ .Values.service.name }}
|
||||
replicas: 1
|
||||
{{- if and (ge (.Capabilities.KubeVersion.Major | int) 1) (ge (.Capabilities.KubeVersion.Minor | int) 7) }}
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -17,9 +17,9 @@ license: "not accepted"
|
||||
|
||||
image:
|
||||
# repository is the container repository to use, which must contain IBM MQ Advanced
|
||||
repository:
|
||||
repository: ibm-mqadvanced-server
|
||||
# tag is the tag to use for the container repository
|
||||
tag:
|
||||
tag: 9.0.4.0-x86_64
|
||||
# pullSecret is the secret to use when pulling the image from a private registry
|
||||
pullSecret:
|
||||
# pullPolicy is either IfNotPresent or Always (https://kubernetes.io/docs/concepts/containers/images/)
|
||||
|
||||
@@ -23,22 +23,10 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//const mainDir string := "/mnt/mqm"
|
||||
const mqmUID uint32 = 999
|
||||
const mqmGID uint32 = 999
|
||||
|
||||
func createVolume(path string) error {
|
||||
// fi, err := os.Stat(path)
|
||||
// if err != nil {
|
||||
// if os.IsNotExist(err) {
|
||||
// // TODO: Should this be fatal?
|
||||
// //log.Warnf("No volume found under %v", path)
|
||||
// return nil
|
||||
// } else {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//log.Printf("%v details: %v", path, fi.Sys())
|
||||
dataPath := filepath.Join(path, "data")
|
||||
fi, err := os.Stat(dataPath)
|
||||
if err != nil {
|
||||
@@ -57,8 +45,6 @@ func createVolume(path string) error {
|
||||
}
|
||||
sys := fi.Sys()
|
||||
if sys != nil && runtime.GOOS == "linux" {
|
||||
// log.Printf("Checking UID/GID for %v", dataPath)
|
||||
//log.Debugf("Checking UID/GID for %v", dataPath)
|
||||
stat := sys.(*syscall.Stat_t)
|
||||
if stat.Uid != mqmUID || stat.Gid != mqmGID {
|
||||
err = os.Chown(dataPath, int(mqmUID), int(mqmGID))
|
||||
@@ -70,18 +56,3 @@ func createVolume(path string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If /mnt/mqm exists
|
||||
// If /mnt/mqm contains a "data" directory AND data is owned by mqm:mqm AND data is writeable by mqm:mqm then
|
||||
// Create Symlink from /var/mqm to /mnt/mqm/data
|
||||
// Else
|
||||
// // Try to sort it out
|
||||
// Create directory /mnt/mqm/data
|
||||
// If directory not already owned by mqm:mqm
|
||||
// chown mqm:mqm
|
||||
// if error
|
||||
// delete directory again if empty
|
||||
// if directory not already 0755
|
||||
// chmod 0755
|
||||
// if error
|
||||
// delete directory again if empty
|
||||
|
||||
@@ -125,7 +125,6 @@ func getQueueManagerName() (string, error) {
|
||||
// runCommand runs an OS command. On Linux it waits for the command to
|
||||
// complete and returns the exit status (return code).
|
||||
func runCommand(name string, arg ...string) (string, int, error) {
|
||||
// log.Debugf("Running command %v %v", name, arg)
|
||||
cmd := exec.Command(name, arg...)
|
||||
// Run the command and wait for completion
|
||||
out, err := cmd.CombinedOutput()
|
||||
@@ -133,12 +132,8 @@ func runCommand(name string, arg ...string) (string, int, error) {
|
||||
var rc int
|
||||
// Only works on Linux
|
||||
if runtime.GOOS == "linux" {
|
||||
// func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
|
||||
var ws unix.WaitStatus
|
||||
//var rusage syscall.Rusage
|
||||
unix.Wait4(cmd.Process.Pid, &ws, 0, nil)
|
||||
//ee := err.(*os.SyscallError)
|
||||
//ws := ee.Sys().(syscall.WaitStatus)
|
||||
rc = ws.ExitStatus()
|
||||
} else {
|
||||
rc = -1
|
||||
@@ -191,6 +186,7 @@ func startQueueManager() {
|
||||
if err != nil {
|
||||
log.Fatalf("Error %v starting queue manager: %v", rc, string(out))
|
||||
}
|
||||
log.Println("Started queue manager")
|
||||
}
|
||||
|
||||
func configureQueueManager() {
|
||||
@@ -273,40 +269,9 @@ func createReaper() {
|
||||
}()
|
||||
}
|
||||
|
||||
// mirrorLog tails the specified file, and logs each line.
|
||||
// This is useful for usability, as the container console log can show
|
||||
// messages from the MQ log.
|
||||
// func mirrorLog(path string) error {
|
||||
// tail, err := tail.TailFile(path, tail.Config{
|
||||
// ReOpen: true,
|
||||
// Follow: true,
|
||||
// Poll: true,
|
||||
// Location: &tail.SeekInfo{
|
||||
// Offset: 0,
|
||||
// // End of file
|
||||
// Whence: 2,
|
||||
// },
|
||||
// Logger: tail.DiscardingLogger,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// go func() {
|
||||
// for line := range tail.Lines {
|
||||
// // TODO: Unless we parse the message, the timestamp will be (slightly) wrong
|
||||
// if strings.HasPrefix(line.Text, "AMQ") {
|
||||
// // TODO: Extended characters don't print correctly
|
||||
// log.Println(line.Text)
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func main() {
|
||||
createReaper()
|
||||
checkLicense()
|
||||
|
||||
// Start SIGTERM handler channel
|
||||
done := createTerminateChannel()
|
||||
|
||||
@@ -315,13 +280,13 @@ func main() {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Printf("Using queue manager name: %v", name)
|
||||
|
||||
logConfig()
|
||||
err = createVolume("/mnt/mqm")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
createDirStructure()
|
||||
//mirrorLog("/var/mqm/qmgrs/" + name + "/errors/AMQERR01.LOG")
|
||||
createQueueManager(name)
|
||||
updateCommandLevel()
|
||||
startQueueManager()
|
||||
|
||||
@@ -18,9 +18,11 @@ package main
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os/user"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/pkg/linux/capabilities"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -54,6 +56,25 @@ func logBaseImage() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func logUser() {
|
||||
u, err := user.Current()
|
||||
if err == nil {
|
||||
log.Printf("Running as user ID %v (%v) with primary group %v", u.Uid, u.Name, u.Gid)
|
||||
}
|
||||
}
|
||||
|
||||
func logCapabilities() {
|
||||
status, err := readProc("/proc/1/status")
|
||||
if err != nil {
|
||||
// Ignore
|
||||
return
|
||||
}
|
||||
caps, err := capabilities.DetectCapabilities(status)
|
||||
if err == nil {
|
||||
log.Printf("Detected capabilities: %v", strings.Join(caps, ","))
|
||||
}
|
||||
}
|
||||
|
||||
func readProc(filename string) (value string, err error) {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -106,13 +127,6 @@ func checkFS(path string) {
|
||||
|
||||
func logConfig() {
|
||||
log.Printf("CPU architecture: %v", runtime.GOARCH)
|
||||
// TODO: You can't use os.user if you're cross-compiling
|
||||
// u, err := user.Current()
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// } else {
|
||||
// log.Printf("Running as user ID %v (%v) with primary group %v", u.Uid, u.Name, u.Gid)
|
||||
// }
|
||||
if runtime.GOOS == "linux" {
|
||||
var err error
|
||||
osr, err := readProc("/proc/sys/kernel/osrelease")
|
||||
@@ -128,6 +142,8 @@ func logConfig() {
|
||||
} else {
|
||||
log.Printf("Maximum file handles: %v", fileMax)
|
||||
}
|
||||
logUser()
|
||||
logCapabilities()
|
||||
readMounts()
|
||||
} else {
|
||||
log.Fatalf("Unsupported platform: %v", runtime.GOOS)
|
||||
|
||||
@@ -34,7 +34,6 @@ apt-get install -y --no-install-recommends \
|
||||
gawk \
|
||||
grep \
|
||||
libc-bin \
|
||||
lsb-release \
|
||||
mount \
|
||||
passwd \
|
||||
procps \
|
||||
@@ -43,20 +42,33 @@ apt-get install -y --no-install-recommends \
|
||||
util-linux
|
||||
|
||||
# Download and extract the MQ installation files
|
||||
mkdir -p /tmp/mq
|
||||
cd /tmp/mq
|
||||
DIR_EXTRACT=/tmp/mq
|
||||
mkdir -p ${DIR_EXTRACT}
|
||||
cd ${DIR_EXTRACT}
|
||||
curl -LO $MQ_URL
|
||||
tar -zxvf ./*.tar.gz
|
||||
|
||||
# Remove packages only needed by this script
|
||||
apt-get purge -y \
|
||||
ca-certificates \
|
||||
curl
|
||||
|
||||
# Remove any orphaned packages
|
||||
apt-get autoremove -y
|
||||
|
||||
# Recommended: Create the mqm user ID with a fixed UID and group, so that the file permissions work between different images
|
||||
groupadd --system --gid 999 mqm
|
||||
useradd --system --uid 999 --gid mqm mqm
|
||||
usermod -G mqm root
|
||||
cd /tmp/mq/DebianMQServer
|
||||
|
||||
# Find directory containing .deb files
|
||||
DIR_DEB=$(find ${DIR_EXTRACT} -name "*.deb" -printf "%h\n" | sort -u | head -1)
|
||||
# Find location of mqlicense.sh
|
||||
MQLICENSE=$(find ${DIR_EXTRACT} -name "mqlicense.sh")
|
||||
|
||||
# Accept the MQ license
|
||||
./mqlicense.sh -text_only -accept
|
||||
echo "deb [trusted=yes] file:/tmp/mq/DebianMQServer ./" > /etc/apt/sources.list.d/IBM_MQ.list
|
||||
${MQLICENSE} -text_only -accept
|
||||
echo "deb [trusted=yes] file:${DIR_DEB} ./" > /etc/apt/sources.list.d/IBM_MQ.list
|
||||
|
||||
# Install MQ using the DEB packages
|
||||
apt-get update
|
||||
@@ -73,7 +85,7 @@ find /opt/mqm -name '*.tar.gz' -delete
|
||||
|
||||
# Clean up all the downloaded files
|
||||
rm -f /etc/apt/sources.list.d/IBM_MQ.list
|
||||
rm -rf /tmp/mq
|
||||
rm -rf ${DIR_EXTRACT}
|
||||
|
||||
# Apply any bug fixes not included in base Ubuntu or MQ image.
|
||||
# Don't upgrade everything based on Docker best practices https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#run
|
||||
@@ -81,6 +93,8 @@ apt-get upgrade -y libkrb5-26-heimdal
|
||||
apt-get upgrade -y libexpat1
|
||||
|
||||
# End of bug fixes
|
||||
|
||||
# Clean up cached apt files
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Optional: Update the command prompt with the MQ version
|
||||
|
||||
158
pkg/linux/capabilities/capabilities.go
Normal file
158
pkg/linux/capabilities/capabilities.go
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// capabilities allows querying of information on Linux capabilities
|
||||
package capabilities
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DetectCapabilities determines Linux capabilities, based on the contents of a Linux "status" file.
|
||||
// For example, the contents of file `/proc/1/status`
|
||||
func DetectCapabilities(status string) ([]string, error) {
|
||||
lines := strings.Split(status, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "CapPrm:") {
|
||||
words := strings.Fields(line)
|
||||
cap, err := strconv.ParseUint(words[1], 16, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getCapabilities(cap), nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Unable to detect capabilities")
|
||||
}
|
||||
|
||||
// getCapabilities converts an encoded uint64 into a slice of string names of Linux capabilities
|
||||
func getCapabilities(cap uint64) []string {
|
||||
caps := make([]string, 0, 37)
|
||||
if cap&0x0000000040000000 == 0x0000000040000000 {
|
||||
caps = append(caps, "AUDIT_CONTROL")
|
||||
}
|
||||
if cap&0x0000000020000000 == 0x0000000020000000 {
|
||||
caps = append(caps, "AUDIT_WRITE")
|
||||
}
|
||||
if cap&0x0000001000000000 == 0x0000001000000000 {
|
||||
caps = append(caps, "BLOCK_SUSPEND")
|
||||
}
|
||||
if cap&0x0000000000000001 == 0x0000000000000001 {
|
||||
caps = append(caps, "CHOWN")
|
||||
}
|
||||
if cap&0x0000000000000002 == 0x0000000000000002 {
|
||||
caps = append(caps, "DAC_OVERRIDE")
|
||||
}
|
||||
if cap&0x0000000000000004 == 0x0000000000000004 {
|
||||
caps = append(caps, "DAC_READ_SEARCH")
|
||||
}
|
||||
if cap&0x0000000000000008 == 0x0000000000000008 {
|
||||
caps = append(caps, "FOWNER")
|
||||
}
|
||||
if cap&0x0000000000000010 == 0x0000000000000010 {
|
||||
caps = append(caps, "FSETID")
|
||||
}
|
||||
if cap&0x0000000000004000 == 0x0000000000004000 {
|
||||
caps = append(caps, "IPC_LOCK")
|
||||
}
|
||||
if cap&0x0000000000008000 == 0x0000000000008000 {
|
||||
caps = append(caps, "IPC_OWNER")
|
||||
}
|
||||
if cap&0x0000000000000020 == 0x0000000000000020 {
|
||||
caps = append(caps, "KILL")
|
||||
}
|
||||
if cap&0x0000000010000000 == 0x0000000010000000 {
|
||||
caps = append(caps, "LEASE")
|
||||
}
|
||||
if cap&0x0000000000000200 == 0x0000000000000200 {
|
||||
caps = append(caps, "LINUX_IMMUTABLE")
|
||||
}
|
||||
if cap&0x0000000200000000 == 0x0000000200000000 {
|
||||
caps = append(caps, "MAC_ADMIN")
|
||||
}
|
||||
if cap&0x0000000100000000 == 0x0000000100000000 {
|
||||
caps = append(caps, "MAC_OVERRIDE")
|
||||
}
|
||||
if cap&0x0000000008000000 == 0x0000000008000000 {
|
||||
caps = append(caps, "MKNOD")
|
||||
}
|
||||
if cap&0x0000000000001000 == 0x0000000000001000 {
|
||||
caps = append(caps, "NET_ADMIN")
|
||||
}
|
||||
if cap&0x0000000000000400 == 0x0000000000000400 {
|
||||
caps = append(caps, "NET_BIND_SERVICE")
|
||||
}
|
||||
if cap&0x0000000000000800 == 0x0000000000000800 {
|
||||
caps = append(caps, "NET_BROADCAST")
|
||||
}
|
||||
if cap&0x0000000000002000 == 0x0000000000002000 {
|
||||
caps = append(caps, "NET_RAW")
|
||||
}
|
||||
if cap&0x0000000080000000 == 0x0000000080000000 {
|
||||
caps = append(caps, "SETFCAP")
|
||||
}
|
||||
if cap&0x0000000000000040 == 0x0000000000000040 {
|
||||
caps = append(caps, "SETGID")
|
||||
}
|
||||
if cap&0x0000000000000100 == 0x0000000000000100 {
|
||||
caps = append(caps, "SETPCAP")
|
||||
}
|
||||
if cap&0x0000000000000080 == 0x0000000000000080 {
|
||||
caps = append(caps, "SETUID")
|
||||
}
|
||||
if cap&0x0000000400000000 == 0x0000000400000000 {
|
||||
caps = append(caps, "SYSLOG")
|
||||
}
|
||||
if cap&0x0000000000200000 == 0x0000000000200000 {
|
||||
caps = append(caps, "SYS_ADMIN")
|
||||
}
|
||||
if cap&0x0000000000400000 == 0x0000000000400000 {
|
||||
caps = append(caps, "SYS_BOOT")
|
||||
}
|
||||
if cap&0x0000000000040000 == 0x0000000000040000 {
|
||||
caps = append(caps, "SYS_CHROOT")
|
||||
}
|
||||
if cap&0x0000000000010000 == 0x0000000000010000 {
|
||||
caps = append(caps, "SYS_MODULE")
|
||||
}
|
||||
if cap&0x0000000000800000 == 0x0000000000800000 {
|
||||
caps = append(caps, "SYS_NICE")
|
||||
}
|
||||
if cap&0x0000000000100000 == 0x0000000000100000 {
|
||||
caps = append(caps, "SYS_PACCT")
|
||||
}
|
||||
if cap&0x0000000000080000 == 0x0000000000080000 {
|
||||
caps = append(caps, "SYS_PTRACE")
|
||||
}
|
||||
if cap&0x0000000000020000 == 0x0000000000020000 {
|
||||
caps = append(caps, "SYS_RAWIO")
|
||||
}
|
||||
if cap&0x0000000001000000 == 0x0000000001000000 {
|
||||
caps = append(caps, "SYS_RESOURCE")
|
||||
}
|
||||
if cap&0x0000000002000000 == 0x0000000002000000 {
|
||||
caps = append(caps, "SYS_TIME")
|
||||
}
|
||||
if cap&0x0000000004000000 == 0x0000000004000000 {
|
||||
caps = append(caps, "SYS_TTY_CONFIG")
|
||||
}
|
||||
if cap&0x0000000800000000 == 0x0000000800000000 {
|
||||
caps = append(caps, "WAKE_ALARM")
|
||||
}
|
||||
return caps
|
||||
}
|
||||
39
pkg/linux/capabilities/capabilities_test.go
Normal file
39
pkg/linux/capabilities/capabilities_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package capabilities
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var capTests = []struct {
|
||||
in uint64
|
||||
out []string
|
||||
}{
|
||||
{0x0000000040000000, []string{"AUDIT_CONTROL"}},
|
||||
// Default values when you run a Docker container without changing capabilities:
|
||||
{0x00000000a80425fb, []string{"AUDIT_WRITE", "CHOWN", "DAC_OVERRIDE", "FOWNER", "FSETID", "KILL", "MKNOD", "NET_BIND_SERVICE", "NET_RAW", "SETFCAP", "SETGID", "SETPCAP", "SETUID", "SYS_CHROOT"}},
|
||||
}
|
||||
|
||||
func TestGetCapabilities(t *testing.T) {
|
||||
for _, table := range capTests {
|
||||
caps := getCapabilities(table.in)
|
||||
if !reflect.DeepEqual(caps, table.out) {
|
||||
t.Errorf("getCapabilities(%v) - expected %v, got %v", table.in, table.out, caps)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ func TestHelmPredefinedVolume(t *testing.T) {
|
||||
func TestHelmStorageClass(t *testing.T) {
|
||||
cs := kubeLogin(t)
|
||||
release := strings.ToLower(t.Name())
|
||||
assertKubeVersion(t, cs, 1, 6)
|
||||
if !storageClassesDefined(t, cs) {
|
||||
t.Skipf("Skipping test because no storage classes were found")
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -257,4 +258,23 @@ func volumesAvailable(t *testing.T, cs *kubernetes.Clientset) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// assertKubeVersion is used to assert that a test requires a specific version of Kubernetes
|
||||
func assertKubeVersion(t *testing.T, cs *kubernetes.Clientset, major int, minor int) {
|
||||
v, err := cs.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
maj, err := strconv.Atoi(v.Major)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
min, err := strconv.Atoi(v.Minor)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if maj <= major && min < minor {
|
||||
t.Skipf("Skipping test because it's not suitable for Kubernetes %v.%v", v.Major, v.Minor)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: On Minikube, need to make sure Helm is initialized first
|
||||
|
||||
Reference in New Issue
Block a user