Fix: Handle error in job-cost.sh without failing
[releng/global-jjb.git] / shell / job-cost.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: EPL-1.0
3 ##############################################################################
4 # Copyright (c) 2019 The Linux Foundation and others.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Eclipse Public License v1.0
8 # which accompanies this distribution, and is available at
9 # http://www.eclipse.org/legal/epl-v10.html
10 ##############################################################################
11 echo "---> job-cost.sh"
12
13 set -euf -o pipefail
14
15 # shellcheck disable=SC1090
16 source ~/lf-env.sh
17
18 if [[ ! -f /run/cloud-init/result.json && ! -f stack-cost ]]; then
19     # Don't attempt to calculate job cost as build is not running in a
20     # cloud environment
21     echo "INFO: Skipping job cost calculation"
22     exit 0
23 fi
24
25 # AWS job cost not supported, exit
26 cloudtype="$(jq -r .v1.datasource /run/cloud-init/result.json)"
27 if [[ $cloudtype == "DataSourceEc2Local" ]]; then
28     echo "INFO: Not able to calculate job cost on AWS"
29     exit 0
30 fi
31
32 lf-activate-venv zipp==1.1.0 python-openstackclient urllib3~=1.26.15
33
34 if [[ -z ${JOB_NAME:-} ]]; then
35     lf-echo-error "Required Env Variable Unset/Empty: JOB_NAME"
36     exit 1
37 fi
38
39 # Get the cost of the Openstack agents. The 'stack-cost' file is created when
40 # the 'lftools openstack stack cost' command is called from
41 # 'openstack-stack-delete.sh' script. The 'stack-cost' file will only be created
42 # if this is an openstack job.
43 if [[ -f stack-cost ]]; then
44     echo "DEBUG: $(cat stack-cost)"
45     echo "INFO: Retrieving Stack Cost..."
46     if ! stack_cost=$(grep -F "total: " stack-cost | awk '{print $2}'); then
47         echo "ERROR: Unable to retrieve Stack Cost, continuing anyway"
48         stack_cost=0
49     fi
50 else
51     echo "INFO: No Stack..."
52     stack_cost=0
53 fi
54
55 # Retrieve the current uptime (in seconds)
56 # And Convert to integer by truncating fractional part' and round up by one
57 uptime=$(awk '{print int($1 + 1)}' /proc/uptime)
58
59 # EC2 and OpenStack have simiar instace metadata APIs at this IP
60 # AWS docs: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
61 # Nova docs: https://docs.openstack.org/nova/latest/user/metadata.html
62 set +e
63 instance_type=$(curl -s http://169.254.169.254/latest/meta-data/instance-type)
64 result=$?
65 if [[ "$result" -ne 0 ]]; then
66     echo "INFO: Unable to retrieve instance type. Skipping job cost..."
67     exit 0
68 fi
69 set -e
70
71 echo "INFO: Retrieving Pricing Info for: $instance_type"
72 url="https://pricing.vexxhost.net/v1/pricing/$instance_type/cost?seconds=$uptime"
73 json_block=$(curl -s "$url")
74
75 # check if JSON returned and can be parsed
76 if jq . <<< "$json_block" > /dev/null 2>&1; then
77     cost=$(jq .cost <<< "$json_block")
78     resource=$(jq .resource <<< "$json_block" | tr -d '"')
79 else
80     echo "ERROR: Pricing API returned invalid json"
81     cost=0
82     resource='unknown'
83 fi
84
85 # Archive the cost date
86 mkdir -p "${WORKSPACE}/archives/cost"
87
88 echo "INFO: Archiving Costs"
89
90 # Set the timestamp in GMT
91 # This format is readable by spreadsheet and is easily sortable
92 date=$(TZ=GMT date +'%Y-%m-%d %H:%M:%S')
93
94 # Format the uptime, cost & stack_cost fields
95 printf "%s,%s,%s,%s,%d,%.2f,%.2f,%s\n" "${JOB_NAME:-}" "${BUILD_NUMBER:-}" "$date" \
96        "$resource" "$uptime" "$cost" "$stack_cost" "${BUILD_RESULT:-}" > "${WORKSPACE}/archives/cost.csv"