-
Notifications
You must be signed in to change notification settings - Fork 2
/
install.sh
executable file
·230 lines (192 loc) · 6.88 KB
/
install.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#!/usr/bin/env bash
# Usage:
# ./install.sh github.com/owner/plugin <revision> <version>
#
# If <revision> matches a git tag specifying a semantic version
# the plugin will be installed *as* that version.
#
# If the <version> argument is provided, the plugin will
# be installed as the version specified
#
# <revision> and <version> are not required, by default
# this script will install the latest version
#
# Installing from local paths is also supported, e.g.
#
# ./install.sh /path/to/tf-plugin
# Undefined variables are errors.
set -euoE pipefail
errcho ()
{
printf "%s\n" "$@" 1>&2
}
errxit ()
{
errcho "$@"
# shellcheck disable=SC2119
errcleanup
}
debug ()
{
if [ -n ${TF_PLUGIN_INSTALLER_DEBUG:-''} ]; then
errcho "$@"
fi
}
_pushd () {
command pushd "$@" > /dev/null
}
_popd () {
command popd > /dev/null
}
_cmd_exists () {
if ! type "$*" &> /dev/null; then
errcho "$* command not installed"
return 1
fi
}
_realpath () {
if _cmd_exists realpath; then
realpath "$@"
return $?
else
readlink -f "$@"
return $?
fi
}
cleanup() {
if [[ -d ${_tfpi_tmp_workdir:-} ]]; then
# shellcheck disable=SC2086
echo "Cleaning up tmp workdir [ ${_tfpi_tmp_workdir} ]"
rm -rf "${_tfpi_tmp_workdir}"
echo "🛀"
fi
}
# shellcheck disable=SC2120
errcleanup() {
errcho "⛔️ terraform plugin installer execution failed."
if [ -n "${1:-}" ]; then
errcho "⏩ Error at line ${1}."
fi
cleanup
exit 1
}
intcleanup() {
errcho "🍿 Script discontinued."
cleanup
exit 1
}
trap 'errcleanup ${LINENO}' ERR
trap 'intcleanup' SIGHUP SIGINT SIGTERM
# The following option is not used, *unless*:
# 1) you want to install a valid version git ref
# as a version not equal to that git ref e.g.
# install plugin on git tag == 1.0.0 *as*
# version 2.0.1 (for some reason)
# 2) you want to install from a git sha *as* the
# version specified. If you want to install from
# a git sha, the version defaults to 0.0.1
INSTALL_AS_VERSION="${3:-v0.0.1}"
V_VERSION_REGEX='^v.*[0-9]$'
# VERSION_REGEX='^.*[0-9]$'
# TODO: allow installing from a local file path
REPOSITORY="${1:-}"
if [[ -z ${REPOSITORY} ]]; then
errxit "Full plugin name required e.g. 'github.com/phillbaker/terraform-provider-mailgunv3'"
fi
if [[ -d "${REPOSITORY}" ]]; then
echo "Source repository [ ${REPOSITORY} ] is to a local path. Attempting to discover remote URL."
_pushd "$(_realpath "${REPOSITORY}")"
# WARNING: WITHIN THIS BLOCK YOU ARE NOW IN A LOCAL REPOSITORY THAT SOMEONE PROBABLY CARES ABOUT.
# PERFORM EXCLUSIVELY READ-ONLY COMMANDS.
_current_remote=$(git branch -vv --no-color | grep -e '^\*' | sed -E 's/.*\[(.*)\/[a-zA-Z0-9\ \:\,\_\.-]+\].*/\1/')
REPOSITORY_URL=$(git remote get-url "${_current_remote}")
echo "Discovered source url from local repo: ${REPOSITORY_URL}"
_popd
else
# If target is not a local filesytem path, check scheme
if [[ ! "${REPOSITORY}" =~ (:\/\/)|(^git@) ]]; then
# if the protocol/scheme is not specified, use 'https'
# github and gitlab use 'git' user. address other use cases if/when they arise.
REPOSITORY="https://"${REPOSITORY}
REPOSITORY_URL="${REPOSITORY}"
else
# Provided url already includes scheme
REPOSITORY_URL="${REPOSITORY}"
fi
fi
REPO_REGEX='s/(.*:\/\/|^git@)(.*)([\/:]{1})([a-zA-Z0-9_\.-]{1,})([\/]{1})([a-zA-Z0-9_\.-]{1,}$)'
# Remove trailing .git if present
REPOSITORY_URL="${REPOSITORY_URL/%\.git/''}"
# the 2nd sed here is to parse out any user:<token> notations
REPOSITORY_URL_DOMAIN=$(echo "${REPOSITORY_URL}" | sed -E "${REPO_REGEX}"'/\2/' | sed -E "s/(^[a-zA-Z0-9_-]{0,38}\:{1})([a-zA-Z0-9_]{5,40})(\@?)"'//')
REPOSITORY_OWNER=$(echo "${REPOSITORY_URL}" | sed -E "${REPO_REGEX}"'/\4/')
REPOSITORY_PROJECT_NAME=$(echo "${REPOSITORY_URL}" | sed -E "${REPO_REGEX}"'/\6/')
PLUGIN_SHORTNAME=${REPOSITORY_PROJECT_NAME#"terraform-provider-"}
PLUGIN_SHORTNAME=${PLUGIN_SHORTNAME#"terraform-plugin-"}
debug "Provided Repository URL: ${REPOSITORY}"
debug "Repository URL: ${REPOSITORY_URL}"
debug "Repository URL Domain: ${REPOSITORY_URL_DOMAIN}"
debug "Repository Owner: ${REPOSITORY_OWNER}"
debug "Repository Project Name: ${REPOSITORY_PROJECT_NAME}"
debug "Plugin Shortname: ${PLUGIN_SHORTNAME}"
echo "Installing from ${REPOSITORY}"
function get_latest_version {
VERSIONS=($(git tag --list --format='%(refname:lstrip=2)' | grep -e "${V_VERSION_REGEX}" | sort -r))
if [ ${#VERSIONS[@]} -eq 0 ]; then
errcho "No proper version tags found at ${REPOSITORY}. Using ${INSTALL_AS_VERSION}"
echo "${INSTALL_AS_VERSION}"
else
errcho "Available Versions: ${VERSIONS[*]} (selecting latest)"
echo "${VERSIONS[0]}"
fi
}
_tfpi_tmp_workdir=$(mktemp -t='tfpi-workdir.XXXXXX' -d || errxit "Failed to create tmpdir.")
export _tfpi_tmp_workdir
echo "Working in tmpdir ${_tfpi_tmp_workdir}"
_pushd "${_tfpi_tmp_workdir}"
# clone plugin
_GITDIR="tf-installer-clone-${PLUGIN_SHORTNAME}"
git clone --quiet --depth 1 "${REPOSITORY}" "${_GITDIR}"
_pushd "${_GITDIR}"
git fetch --quiet --tags --update-head-ok
REVISION="${2:-$(get_latest_version)}"
# TODO(maybe): If revision was specified and matches VERSION_REGEX
# but does not match V_VERSION_REGEX, prepend a 'v'.
echo "Building ${REPOSITORY_PROJECT_NAME} version ${REVISION}"
_USING_HEAD=false
git checkout "${REVISION}" --quiet --force || _USING_HEAD=true
# If INSTALL_AS_VERSION was explicitly specified, it must be used.
# If the revision specified is not a valid version, use the fallback.
if [[ -n "${3:-}" ]] || ! [[ "${REVISION}" =~ ${V_VERSION_REGEX} ]] ; then
VERSION="${INSTALL_AS_VERSION}"
echo "Installing revision ${REVISION} as ${VERSION}"
else
VERSION="${REVISION}"
fi
# In any case, double check that the VERSION used is valid.
if ! [[ "${VERSION}" =~ ${V_VERSION_REGEX} ]]; then
errxit "${VERSION} is not a valid sem version ( ${V_VERSION_REGEX})"
fi
debug "Version: ${VERSION}"
if ${_USING_HEAD}; then
echo "Installing HEAD as ${VERSION}."
fi
case "$OSTYPE" in
darwin*) _PLATFORM="darwin_amd64" ;;
solaris*) _PLATFORM="solaris_amd64" ;;
linux*) _PLATFORM="linux_amd64" ;;
cygwin*) _PLATFORM="windows_amd64" ;;
*arm*) _PLATFORM="linux_arm64" ;;
*) errxit "Unknown OSTYPE: ${OSTYPE}" ;;
esac
debug "Platform: ${_PLATFORM}"
# remove 'v' prefix if present for version dir in path
_version=${VERSION#"v"}
# path: HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET
# e.g. -> /.terraform.d/plugins/github.internal.company.com/company/company_project/0.12.6/darwin_amd64
PLUGIN_TARGET="${HOME}/.terraform.d/plugins/${REPOSITORY_URL_DOMAIN}/${REPOSITORY_OWNER}/${PLUGIN_SHORTNAME}/${_version}/${_PLATFORM}/"
mkdir -p "${PLUGIN_TARGET}"
go build -o "${PLUGIN_TARGET}/${REPOSITORY_PROJECT_NAME}_${VERSION}"
echo "Installing ${REPOSITORY_PROJECT_NAME} version ${VERSION}"
echo "Terraform provider '${PLUGIN_SHORTNAME}' version ${VERSION} has been installed into ${PLUGIN_TARGET}"
_popd && _popd && cleanup