Merge pull request #15 from arthurbarr/master

Updates ready for MQ V9.0.4
This commit is contained in:
Arthur Barr
2017-10-31 19:18:23 +00:00
committed by GitHub
21 changed files with 350 additions and 189 deletions

View File

@@ -1,6 +1,3 @@
charts
cmd
downloads
pkg
test
vendor

View File

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

View File

@@ -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"]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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/)

View File

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

View File

@@ -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()

View File

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

View File

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

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

View 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)
}
}
}

View File

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

View File

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