hack/test-cmd.sh
1b64eb52
 #!/bin/bash
 
 # This command checks that the built commands can function together for
 # simple scenarios.  It does not require Docker so it can run in travis.
 
e3bb13a1
 set -o errexit
 set -o nounset
 set -o pipefail
 
b52db8df
 STARTTIME=$(date +%s)
e3bb13a1
 OS_ROOT=$(dirname "${BASH_SOURCE}")/..
064493cb
 cd "${OS_ROOT}"
e3bb13a1
 source "${OS_ROOT}/hack/util.sh"
b1165476
 os::log::install_errexit
 
1b64eb52
 function cleanup()
 {
eeaac221
     out=$?
     pkill -P $$
5b128f6c
     set +e
     kill_all_processes
eeaac221
 
     if [ $out -ne 0 ]; then
         echo "[FAIL] !!!!! Test Failed !!!!"
a29cc306
         echo
da9f1923
         tail -40 "${LOG_DIR}/openshift.log"
a29cc306
         echo
         echo -------------------------------------
         echo
eeaac221
     else
4034c659
         if path=$(go tool -n pprof 2>&1); then
           echo
           echo "pprof: top output"
           echo
da9f1923
           go tool pprof -text ./_output/local/bin/$(os::util::host_platform)/openshift cpu.pprof | head -120
4034c659
         fi
 
eeaac221
         echo
         echo "Complete"
4b1a5e9d
     fi
b52db8df
 
     ENDTIME=$(date +%s); echo "$0 took $(($ENDTIME - $STARTTIME)) seconds"
eeaac221
     exit $out
1b64eb52
 }
 
eeaac221
 trap "exit" INT TERM
 trap "cleanup" EXIT
1b64eb52
 
 set -e
 
cb5bee4a
 function find_tests {
064493cb
   find "${OS_ROOT}/test/cmd" -name '*.sh' | grep -E "${1}" | sort -u
cb5bee4a
 }
064493cb
 tests=( $(find_tests ${1:-.*}) )
cb5bee4a
 
09a8c7d3
 # Setup environment
20648995
 
09a8c7d3
 # test-cmd specific defaults
f2e9db16
 TMPDIR="${TMPDIR:-"/tmp"}"
 BASETMPDIR="${BASETMPDIR:-${TMPDIR}/openshift-cmd}"
9e61a9ff
 LOG_DIR=${BASETMPDIR}/logs
09a8c7d3
 API_HOST=${API_HOST:-127.0.0.1}
 export API_PORT=${API_PORT:-28443}
 
4d75ab9b
 export ETCD_HOST=${ETCD_HOST:-127.0.0.1}
 export ETCD_PORT=${ETCD_PORT:-24001}
 export ETCD_PEER_PORT=${ETCD_PEER_PORT:-27001}
09a8c7d3
 setup_env_vars
4d75ab9b
 export SUDO=''
09a8c7d3
 mkdir -p "${ETCD_DATA_DIR}" "${VOLUME_DIR}" "${FAKE_HOME_DIR}" "${MASTER_CONFIG_DIR}" "${NODE_CONFIG_DIR}" "${LOG_DIR}"
f2e9db16
 reset_tmp_dir
e3bb13a1
 
9e61a9ff
 echo "Logging to ${LOG_DIR}..."
09a8c7d3
 
 # Prevent user environment from colliding with the test setup
 unset KUBECONFIG
 
aa097331
 # test wrapper functions
 ${OS_ROOT}/hack/test-cmd_util.sh > ${BASETMPDIR}/wrappers.txt 2>&1
 
3a866bb8
 
eeaac221
 # handle profiling defaults
 profile="${OPENSHIFT_PROFILE-}"
 unset OPENSHIFT_PROFILE
 if [[ -n "${profile}" ]]; then
     if [[ "${TEST_PROFILE-}" == "cli" ]]; then
         export CLI_PROFILE="${profile}"
     else
06bbefa8
         export WEB_PROFILE="${profile}"
eeaac221
     fi
06bbefa8
 else
   export WEB_PROFILE=cpu
eeaac221
 fi
 
1b64eb52
 # Check openshift version
5e026ad1
 out=$(openshift version)
1b64eb52
 echo openshift: $out
 
eeaac221
 # profile the web
 export OPENSHIFT_PROFILE="${WEB_PROFILE-}"
 
7066dfe7
 # Specify the scheme and port for the listen address, but let the IP auto-discover. Set --public-master to localhost, for a stable link to the console.
40be29be
 echo "[INFO] Create certificates for the OpenShift server to ${MASTER_CONFIG_DIR}"
7066dfe7
 # find the same IP that openshift start will bind to.  This allows access from pods that have to talk back to master
da229170
 SERVER_HOSTNAME_LIST="${PUBLIC_MASTER_HOST},$(openshift start --print-ip),localhost"
7066dfe7
 
d751e6eb
 openshift admin ca create-master-certs \
   --overwrite=false \
   --cert-dir="${MASTER_CONFIG_DIR}" \
   --hostnames="${SERVER_HOSTNAME_LIST}" \
   --master="${MASTER_ADDR}" \
   --public-master="${API_SCHEME}://${PUBLIC_MASTER_HOST}:${API_PORT}"
 
 openshift admin create-node-config \
   --listen="${KUBELET_SCHEME}://0.0.0.0:${KUBELET_PORT}" \
   --node-dir="${NODE_CONFIG_DIR}" \
   --node="${KUBELET_HOST}" \
   --hostnames="${KUBELET_HOST}" \
   --master="${MASTER_ADDR}" \
   --node-client-certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" \
   --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" \
   --signer-cert="${MASTER_CONFIG_DIR}/ca.crt" \
   --signer-key="${MASTER_CONFIG_DIR}/ca.key" \
   --signer-serial="${MASTER_CONFIG_DIR}/ca.serial.txt"
 
 oadm create-bootstrap-policy-file --filename="${MASTER_CONFIG_DIR}/policy.json"
 
 # create openshift config
 openshift start \
   --write-config=${SERVER_CONFIG_DIR} \
   --create-certs=false \
   --master="${API_SCHEME}://${API_HOST}:${API_PORT}" \
   --listen="${API_SCHEME}://${API_HOST}:${API_PORT}" \
   --hostname="${KUBELET_HOST}" \
   --volume-dir="${VOLUME_DIR}" \
   --etcd-dir="${ETCD_DATA_DIR}" \
   --images="${USE_IMAGES}"
 
8049d6db
 # validate config that was generated
 [ "$(openshift ex validate master-config ${MASTER_CONFIG_DIR}/master-config.yaml 2>&1 | grep SUCCESS)" ]
 [ "$(openshift ex validate node-config ${NODE_CONFIG_DIR}/node-config.yaml 2>&1 | grep SUCCESS)" ]
 # breaking the config fails the validation check
09a8c7d3
 cp ${MASTER_CONFIG_DIR}/master-config.yaml ${BASETMPDIR}/master-config-broken.yaml
acb1d123
 os::util::sed '5,10d' ${BASETMPDIR}/master-config-broken.yaml
1eb472bb
 [ "$(openshift ex validate master-config ${BASETMPDIR}/master-config-broken.yaml 2>&1 | grep ERROR)" ]
8049d6db
 
09a8c7d3
 cp ${NODE_CONFIG_DIR}/node-config.yaml ${BASETMPDIR}/node-config-broken.yaml
acb1d123
 os::util::sed '5,10d' ${BASETMPDIR}/node-config-broken.yaml
09a8c7d3
 [ "$(openshift ex validate node-config ${BASETMPDIR}/node-config-broken.yaml 2>&1 | grep ERROR)" ]
8049d6db
 echo "validation: ok"
d751e6eb
 
d864ec44
 # Don't try this at home.  We don't have flags for setting etcd ports in the config, but we want deconflicted ones.  Use sed to replace defaults in a completely unsafe way
09a8c7d3
 os::util::sed "s/:4001$/:${ETCD_PORT}/g" ${SERVER_CONFIG_DIR}/master/master-config.yaml
 os::util::sed "s/:7001$/:${ETCD_PEER_PORT}/g" ${SERVER_CONFIG_DIR}/master/master-config.yaml
d864ec44
 
d751e6eb
 # Start openshift
d864ec44
 OPENSHIFT_ON_PANIC=crash openshift start master \
   --config=${MASTER_CONFIG_DIR}/master-config.yaml \
17e7c256
   --loglevel=5 \
cb974f2c
   &>"${LOG_DIR}/openshift.log" &
d751e6eb
 OS_PID=$!
e5b90d99
 
366baa89
 if [[ "${API_SCHEME}" == "https" ]]; then
40be29be
     export CURL_CA_BUNDLE="${MASTER_CONFIG_DIR}/ca.crt"
     export CURL_CERT="${MASTER_CONFIG_DIR}/admin.crt"
     export CURL_KEY="${MASTER_CONFIG_DIR}/admin.key"
366baa89
 fi
732c47cf
 
d751e6eb
 wait_for_url "${API_SCHEME}://${API_HOST}:${API_PORT}/healthz" "apiserver: " 0.25 80
 wait_for_url "${API_SCHEME}://${API_HOST}:${API_PORT}/healthz/ready" "apiserver(ready): " 0.25 80
ab7ef450
 
eeaac221
 # profile the cli commands
 export OPENSHIFT_PROFILE="${CLI_PROFILE-}"
 
5e026ad1
 #
 # Begin tests
 #
8ed0f91f
 
642797f7
 # create master config as atomic-enterprise just to test it works
 atomic-enterprise start \
09a8c7d3
   --write-config="${BASETMPDIR}/atomic.local.config" \
642797f7
   --create-certs=true \
   --master="${API_SCHEME}://${API_HOST}:${API_PORT}" \
   --listen="${API_SCHEME}://${API_HOST}:${API_PORT}" \
   --hostname="${KUBELET_HOST}" \
   --volume-dir="${VOLUME_DIR}" \
   --etcd-dir="${ETCD_DATA_DIR}" \
   --images="${USE_IMAGES}"
 
 # ensure that DisabledFeatures aren't written to config files
 ! grep -i '\<disabledFeatures\>' \
 	"${MASTER_CONFIG_DIR}/master-config.yaml" \
09a8c7d3
 	"${BASETMPDIR}/atomic.local.config/master/master-config.yaml" \
642797f7
 	"${NODE_CONFIG_DIR}/node-config.yaml"
 
2de77d1a
 # test client not configured
13cc7c6a
 [ "$(oc get services 2>&1 | grep 'No configuration file found, please login')" ]
 unused_port="33333"
 # setting env bypasses the not configured message
 [ "$(KUBERNETES_MASTER=http://${API_HOST}:${unused_port} oc get services 2>&1 | grep 'did you specify the right host or port')" ]
 # setting --server bypasses the not configured message
 [ "$(oc get services --server=http://${API_HOST}:${unused_port} 2>&1 | grep 'did you specify the right host or port')" ]
2de77d1a
 
432e76ef
 # Set KUBERNETES_MASTER for oc from now on
2de77d1a
 export KUBERNETES_MASTER="${API_SCHEME}://${API_HOST}:${API_PORT}"
 
432e76ef
 # Set certificates for oc from now on
2de77d1a
 if [[ "${API_SCHEME}" == "https" ]]; then
     # test bad certificate
432e76ef
     [ "$(oc get services 2>&1 | grep 'certificate signed by unknown authority')" ]
2de77d1a
 fi
 
cb5bee4a
 
da0ec690
 # login and logout tests
631a5a60
 # --token and --username are mutually exclusive
432e76ef
 [ "$(oc login ${KUBERNETES_MASTER} -u test-user --token=tmp --insecure-skip-tls-verify 2>&1 | grep 'mutually exclusive')" ]
631a5a60
 # must only accept one arg (server)
432e76ef
 [ "$(oc login https://server1 https://server2.com 2>&1 | grep 'Only the server URL may be specified')" ]
631a5a60
 # logs in with a valid certificate authority
1eb472bb
 oc login ${KUBERNETES_MASTER} --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" -u test-user -p anything --api-version=v1
 grep -q "v1" ${HOME}/.kube/config
432e76ef
 oc logout
631a5a60
 # logs in skipping certificate check
432e76ef
 oc login ${KUBERNETES_MASTER} --insecure-skip-tls-verify -u test-user -p anything
631a5a60
 # logs in by an existing and valid token
432e76ef
 temp_token=$(oc config view -o template --template='{{range .users}}{{ index .user.token }}{{end}}')
 [ "$(oc login --token=${temp_token} 2>&1 | grep 'using the token provided')" ]
 oc logout
631a5a60
 # properly parse server port
432e76ef
 [ "$(oc login https://server1:844333 2>&1 | grep 'Not a valid port')" ]
631a5a60
 # properly handle trailing slash
44986a1e
 oc login --server=${KUBERNETES_MASTER} --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" -u test-user -p anything
631a5a60
 # create a new project
432e76ef
 oc new-project project-foo --display-name="my project" --description="boring project description"
 [ "$(oc project | grep 'Using project "project-foo"')" ]
44986a1e
 # new user should get default context
 oc login --server=${KUBERNETES_MASTER} --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" -u new-and-unknown-user -p anything
 [ "$(oc config view | grep current-context | grep /${API_HOST}:${API_PORT}/new-and-unknown-user)" ]
631a5a60
 # denies access after logging out
432e76ef
 oc logout
 [ -z "$(oc get pods | grep 'system:anonymous')" ]
da0ec690
 
40aac47c
 # log in as an image-pruner and test that oadm prune images works against the atomic binary
 oadm policy add-cluster-role-to-user system:image-pruner pruner --config="${MASTER_CONFIG_DIR}/admin.kubeconfig"
44986a1e
 oc login --server=${KUBERNETES_MASTER} --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" -u pruner -p anything
40aac47c
 # this shouldn't fail but instead output "Dry run enabled - no modifications will be made. Add --confirm to remove images"
 oadm prune images
 
da0ec690
 # log in and set project to use from now on
432e76ef
 oc login --server=${KUBERNETES_MASTER} --certificate-authority="${MASTER_CONFIG_DIR}/ca.crt" -u test-user -p anything
 oc get projects
 oc project project-foo
44986a1e
 [ "$(oc config view | grep current-context | grep project-foo/${API_HOST}:${API_PORT}/test-user)" ]
a63fc69e
 [ "$(oc whoami | grep 'test-user')" ]
1d678d0c
 [ "$(oc whoami --config="${MASTER_CONFIG_DIR}/admin.kubeconfig" | grep 'system:admin')" ]
f7353122
 [ -n "$(oc whoami -t)" ]
 [ -n "$(oc whoami -c)" ]
2da2b953
 
2de77d1a
 # test config files from the --config flag
432e76ef
 oc get services --config="${MASTER_CONFIG_DIR}/admin.kubeconfig"
2de77d1a
 
 # test config files from env vars
d46b3af9
 KUBECONFIG="${MASTER_CONFIG_DIR}/admin.kubeconfig" oc get services
2de77d1a
 
 # test config files in the home directory
3cabc0f8
 mkdir -p ${HOME}/.kube
 cp ${MASTER_CONFIG_DIR}/admin.kubeconfig ${HOME}/.kube/config
432e76ef
 oc get services
3cabc0f8
 mv ${HOME}/.kube/config ${HOME}/.kube/non-default-config
2de77d1a
 echo "config files: ok"
 
d46b3af9
 # from this point every command will use config from the KUBECONFIG env var
cb5bee4a
 export KUBECONFIG="${HOME}/.kube/non-default-config"
2a6a1ee0
 export CLUSTER_ADMIN_CONTEXT=$(oc config view --flatten -o template --template='{{index . "current-context"}}')
2de77d1a
 
48a2bba1
 
cb5bee4a
 # NOTE: Do not add tests here, add them to test/cmd/*.
 # Tests should assume they run in an empty project, and should be reentrant if possible
 # to make it easy to run individual tests
 for test in "${tests[@]}"; do
   echo
   echo "++ ${test}"
   name=$(basename ${test} .sh)
1bac161a
 
   # switch back to a standard identity. This prevents individual tests from changing contexts and messing up other tests
   oc project ${CLUSTER_ADMIN_CONTEXT}
cb5bee4a
   oc new-project "cmd-${name}"
   ${test}
ddb0a02c
   oc project ${CLUSTER_ADMIN_CONTEXT}
cb5bee4a
   oc delete project "cmd-${name}"
 done
 
4034c659
 
cb5bee4a
 # Done
4034c659
 echo
 echo
d7789ba3
 wait_for_url "${API_SCHEME}://${API_HOST}:${API_PORT}/metrics" "metrics: " 0.25 80 > "${LOG_DIR}/metrics.log"
 grep "request_count" "${LOG_DIR}/metrics.log"
4034c659
 echo
 echo
eac4945c
 echo "test-cmd: ok"