1#!/usr/bin/env bash
2
3# Copyright 2016 The Kubernetes Authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Make bucket and a folder for e2e-node test logs.
18# Populate the folder from the logs stored in /tmp/_artifacts/ in the same way as a
19# jenkins build would, and then print the URL to view the test results on Gubernator
20
21set -o errexit
22set -o nounset
23set -o pipefail
24
25KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/../..
26source "${KUBE_ROOT}/hack/lib/logging.sh"
27
28
29if [[ $# -eq 0 || ! $1 =~ ^[Yy]$ ]]; then
30  read -r -p "Do you want to run gubernator.sh and upload logs publicly to GCS? [y/n]" yn
31  echo
32  if [[ ! $yn =~ ^[Yy]$ ]]; then
33      exit 1
34  fi
35fi
36
37# Check that user has gsutil
38if [[ $(which gsutil) == "" ]]; then
39  echo "Could not find gsutil when running \`which gsutil\`"
40  exit 1
41fi
42
43# Check that user has gcloud
44if [[ $(which gcloud) == "" ]]; then
45  echo "Could not find gcloud when running: \`which gcloud\`"
46  exit 1
47fi
48
49# Check that user has Credentialed Active account
50if ! gcloud auth list | grep -q "ACTIVE"; then
51  echo "Could not find active account when running: \`gcloud auth list\`"
52  exit 1
53fi
54
55readonly gcs_acl="public-read"
56bucket_name="${USER}-g8r-logs"
57echo ""
58V=2 kube::log::status "Using bucket ${bucket_name}"
59
60# Check if the bucket exists
61if ! gsutil ls gs:// | grep -q "gs://${bucket_name}/"; then
62  V=2 kube::log::status "Creating public bucket ${bucket_name}"
63  gsutil mb "gs://${bucket_name}/"
64  # Make all files in the bucket publicly readable
65  gsutil acl ch -u AllUsers:R "gs://${bucket_name}"
66else
67  V=2 kube::log::status "Bucket already exists"
68fi
69
70# Path for e2e-node test results
71GCS_JOBS_PATH="gs://${bucket_name}/logs/e2e-node"
72
73ARTIFACTS=${ARTIFACTS:-"/tmp/_artifacts"}
74BUILD_LOG_PATH="${ARTIFACTS}/build-log.txt"
75
76if [[ ! -e $BUILD_LOG_PATH ]]; then
77  echo "Could not find build-log.txt at ${BUILD_LOG_PATH}"
78  exit 1
79fi
80
81# Get start and end timestamps based on build-log.txt file contents
82# Line where the actual tests start
83start_line=$(grep -n -m 1 "^=" "${BUILD_LOG_PATH}" | sed 's/\([0-9]*\).*/\1/')
84# Create text file starting where the tests start
85after_start=$(tail -n "+${start_line}" "${BUILD_LOG_PATH}")
86echo "${after_start}" >> build-log-cut.txt
87# Match the first timestamp
88start_time_raw=$(grep -m 1 -o '[0-9][0-9][0-9][0-9][[:blank:]][0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*' build-log-cut.txt)
89rm build-log-cut.txt
90# Make the date readable by date command (ex: 0101 00:00:00.000 -> 01/01 00:00:00.000)
91start_time=$(echo "${start_time_raw}" | sed 's/^.\{2\}/&\//')
92V=2 kube::log::status "Started at ${start_time}"
93# Match the last timestamp in the build-log file
94end_time=$(grep -o '[0-9][0-9][0-9][0-9][[:blank:]][0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*' "${BUILD_LOG_PATH}" | tail -1 | sed 's/^.\{2\}/&\//')
95# Convert to epoch time for Gubernator
96start_time_epoch=$(date -d "${start_time}" +%s)
97end_time_epoch=$(date -d "${end_time}" +%s)
98
99# Make folder name for build from timestamp
100BUILD_STAMP=$(echo "${start_time}" | sed 's/\///' | sed 's/ /_/')
101
102GCS_LOGS_PATH="${GCS_JOBS_PATH}/${BUILD_STAMP}"
103
104# Check if folder for same logs already exists
105if gsutil ls "${GCS_JOBS_PATH}" | grep -q "${BUILD_STAMP}"; then
106  V=2 kube::log::status "Log files already uploaded"
107  echo "Gubernator linked below:"
108  echo "k8s-gubernator.appspot.com/build/${GCS_LOGS_PATH}?local=on"
109  exit
110fi
111
112while IFS= read -r result; do
113  if [[ $result != "" && $result != "${ARTIFACTS}/results" && $result != "${ARTIFACTS}" ]]; then
114    mv "${result}/"* "${ARTIFACTS}"
115  fi
116done < <(find "${ARTIFACTS}" -type d -name "results")
117
118# Upload log files
119for upload_attempt in $(seq 3); do
120  if [[ -d "${ARTIFACTS}" && -n $(ls -A "${ARTIFACTS}") ]]; then
121    V=2 kube::log::status "Uploading artifacts"
122    gsutil -m -q -o "GSUtil:use_magicfile=True" cp -a "${gcs_acl}" -r -c \
123      -z log,xml,json "${ARTIFACTS}" "${GCS_LOGS_PATH}/artifacts" || continue
124  fi
125  break
126done
127for upload_attempt in $(seq 3); do
128  if [[ -e "${BUILD_LOG_PATH}" ]]; then
129    V=2 kube::log::status "Uploading build log"
130    gsutil -q cp -Z -a "${gcs_acl}" "${BUILD_LOG_PATH}" "${GCS_LOGS_PATH}" || continue
131  fi
132  break
133done
134
135
136# Find the k8s version for started.json
137version=""
138if [[ -e "version" ]]; then
139  version=$(cat "version")
140elif [[ -e "hack/lib/version.sh" ]]; then
141  source "hack/lib/version.sh"
142  kube::version::get_version_vars
143  version="${KUBE_GIT_VERSION-}"
144fi
145if [[ -n "${version}" ]]; then
146  V=2 kube::log::status "Found Kubernetes version: ${version}"
147else
148  V=2 kube::log::status "Could not find Kubernetes version"
149fi
150
151#Find build result from build-log.txt
152if grep -Fxq "Test Suite Passed" "${BUILD_LOG_PATH}"
153  then
154    build_result="SUCCESS"
155else
156    build_result="FAILURE"
157fi
158
159V=4 kube::log::status "Build result is ${build_result}"
160
161if [[ -e "${ARTIFACTS}/started.json" ]]; then
162  rm "${ARTIFACTS}/started.json"
163fi
164
165if [[ -e "${ARTIFACTS}/finished.json" ]]; then
166  rm "${ARTIFACTS}/finished.json"
167fi
168
169V=2 kube::log::status "Constructing started.json and finished.json files"
170cat <<EOF >"${ARTIFACTS}/started.json"
171{
172    "version": "${version}",
173    "timestamp": ${start_time_epoch},
174    "jenkins-node": "${NODE_NAME:-}"
175}
176EOF
177
178
179cat <<EOF >"${ARTIFACTS}/finished.json"
180{
181    "result": "${build_result}",
182    "timestamp": ${end_time_epoch}
183}
184EOF
185
186
187# Upload started.json
188V=2 kube::log::status "Uploading started.json and finished.json"
189V=2 kube::log::status "Run started at ${start_time}"
190json_file="${GCS_LOGS_PATH}/started.json"
191
192for upload_attempt in $(seq 3); do
193  V=2 kube::log::status "Uploading started.json to ${json_file} (attempt ${upload_attempt})"
194  gsutil -q -h "Content-Type:application/json" cp -a "${gcs_acl}" "${ARTIFACTS}/started.json" \
195    "${json_file}" || continue
196  break
197done
198
199# Upload finished.json
200for upload_attempt in $(seq 3); do
201  V=2 kube::log::status "Uploading finished.json to ${GCS_LOGS_PATH} (attempt ${upload_attempt})"
202  gsutil -q -h "Content-Type:application/json" cp -a "${gcs_acl}" "${ARTIFACTS}/finished.json" \
203    "${GCS_LOGS_PATH}/finished.json" || continue
204  break
205done
206
207
208echo "Gubernator linked below:"
209echo "k8s-gubernator.appspot.com/build/${bucket_name}/logs/e2e-node/${BUILD_STAMP}"
210