Skip to content

Commit

Permalink
Add curl-able install script to streamline installation across systems (
Browse files Browse the repository at this point in the history
#158)

* Detect supported system type and version and install correct pacakges
* Offer to fall back to latest available package for distro if distro supported but version is not
* If gnupg is not installed on Debian (required for adding our signing keys), prompt to install it
* Automatically add API key to config file if PGA_API_KEY is set
* Automatically add API base url to config file if PGA_API_BASEURL is set
* Automatically run guided setup after package install if PGA_GUIDED_SETUP is set
* Support non-interactive mode (yes to all prompts) if PGA_INSTALL_NONINTERACTIVE is set
  - runs `--recommended` guided setup if PGA_GUIDED_SETUP is also set
* Add shellcheck to CI
* Add integration test with checked-in install script installing latest-published packages
* Publish install script to packages S3 bucket when publishing packages
* Fix .PHONY targets in packages/repo Makefile
  • Loading branch information
msakrejda authored Mar 10, 2021
1 parent 943f97b commit b32a38e
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ jobs:
make build OUTFILE=pganalyze-collector-linux-amd64
make test
make integration_test
shellcheck contrib/install.sh
204 changes: 204 additions & 0 deletions contrib/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#!/bin/bash

set -e

fail () {
>&2 echo
>&2 echo "Install failed: $1"
>&2 echo
>&2 echo "Please contact [email protected] for help and include information about your platform"
exit 1
}

user_input=''
yum_opts=''
apt_opts=''
pgags_opts=''
if [ -n "$PGA_INSTALL_NONINTERACTIVE" ];
then
user_input=/dev/null
apt_opts='--yes'
yum_opts='--assumeyes'
pgags_opts="--recommended --db-name=${DB_NAME:-postgres}"
else
user_input=/dev/tty
fi

confirm () {
if [ -n "$PGA_INSTALL_NONINTERACTIVE" ];
then
return 0
fi

local confirmation
# N.B.: default is always yes
read -r -n1 -p "$1 [Y/n]" confirmation <$user_input
[ -z "$confirmation" ] || [[ "$confirmation" =~ [Yy] ]]
}

pkg=''
distribution=''
version=''

if ! test -r /etc/os-release;
then
fail "cannot read /etc/os-release to determine distribution"
fi

arch=$(uname -m)
if [ "$arch" != 'x86_64' ];
then
fail "unsupported architecture: $arch"
fi

if grep -q '^ID="amzn"$' /etc/os-release && grep -q '^VERSION_ID="2"$' /etc/os-release;
then
# Amazon Linux 2, based on RHEL7
pkg=yum
distribution=el
version=7
elif grep -q '^ID="rhel"$' /etc/os-release;
then
# RHEL
pkg=yum
distribution=el
version=$(grep VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"' | cut -d. -f1)
if [ "$version" != 7 ] && [ "$version" != 8 ];
then
if confirm "Unsupported RHEL version; try RHEL8 package?";
then
version=8
else
fail "unrecognized RHEL version: ${version}"
fi
fi
elif grep -q '^ID=fedora$' /etc/os-release;
then
# Fedora
pkg=yum
distribution=fedora
version=$(grep VERSION_ID /etc/os-release | cut -d= -f2)

if [ "$version" != 30 ] && [ "$version" != 29 ];
then
if confirm "Unsupported Fedora version; try Fedora 30 package?";
then
version=30
else
fail "unrecognized Fedora version: ${version}"
fi
fi
elif grep -q '^ID=ubuntu$' /etc/os-release;
then
# Ubuntu
pkg=deb
distribution=ubuntu
version=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2)
if [ "$version" != focal ] && [ "$version" != bionic ] && [ "$version" != xenial ];
then
if confirm "Unsupported Ubuntu version; try Ubuntu Focal (20.04) package?";
then
version=focal
else
fail "unrecognized Ubuntu version: ${version}"
fi
fi
elif grep -q '^ID=debian$' /etc/os-release;
then
# Debian
pkg=deb
distribution=debian
version=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2)
if [ "$version" != buster ] && [ "$version" != stretch ];
then
if confirm "Unsupported Debian version; try Debian Buster (10) package?";
then
version=buster
else
fail "unrecognized Debian version: ${version}"
fi
fi
else
>&2 cat /etc/os-release
fail "unrecognized distribution: ${distribution}"
fi

# If we're already running as sudo or root, no need to do anything;
# if we're not, set up sudo for relevant commands
maybe_sudo=''
if [ "$(id -u)" != "0" ]; then
maybe_sudo=$(command -v sudo)
echo "This script requires superuser access to install packages"

if [ -z "$maybe_sudo" ];
then
fail "not running as root and could not find sudo command"
fi

echo "You may be prompted for your password by sudo"

# clear any previous sudo permission to avoid inadvertent confirmation
$maybe_sudo -k
fi

if [ "$pkg" = yum ];
then
echo "[pganalyze_collector]
name=pganalyze_collector
baseurl=https://packages.pganalyze.com/${distribution}/${version}
repo_gpgcheck=1
enabled=1
gpgkey=https://packages.pganalyze.com/pganalyze_signing_key.asc
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300" | $maybe_sudo tee -a /etc/yum.repos.d/pganalyze_collector.repo
$maybe_sudo yum $yum_opts makecache <$user_input
$maybe_sudo yum $yum_opts install pganalyze-collector <$user_input
elif [ "$pkg" = deb ];
then
# on Debian, gnupg, required for apt-key add, is not installed by default, so install
# it before trying to invoke it if necessary
if ! dpkg --verify gnupg 2>/dev/null && ! dpkg --verify gnupg1 2>/dev/null && ! dpkg --verify gnupg2 2>/dev/null;
then
if confirm "The gnupg package is required to verify the collector package signature; install it now?";
then
$maybe_sudo apt-get $apt_opts update <$user_input
$maybe_sudo apt-get $apt_opts install gnupg <$user_input
else
fail "cannot install without gnupg"
fi
fi
apt_source="deb [arch=amd64] https://packages.pganalyze.com/${distribution}/${version}/ stable main"
curl -L https://packages.pganalyze.com/pganalyze_signing_key.asc | $maybe_sudo apt-key add -
echo "$apt_source" | $maybe_sudo tee /etc/apt/sources.list.d/pganalyze_collector.list
$maybe_sudo apt-get $apt_opts update <$user_input
$maybe_sudo apt-get $apt_opts install pganalyze-collector <$user_input
else
fail "unrecognized package kind: $pkg"
fi

if [ -n "$PGA_API_BASE_URL" ];
then
$maybe_sudo sed -i "/^\[pganalyze\]$/a api_base_url = ${PGA_API_BASE_URL}" /etc/pganalyze-collector.conf
fi

if [ -n "$PGA_API_KEY" ];
then
$maybe_sudo sed -i "s/^#api_key = your_api_key$/api_key = ${PGA_API_KEY}/" /etc/pganalyze-collector.conf
fi

echo "Checking install by running 'pganalyze-collector --version'"
pganalyze-collector --version
echo

echo "The pganalyze collector was installed successfully"
echo

if [ -n "$PGA_GUIDED_SETUP" ];
then
# We want all opts passed separately here: not sure why this is not an issue above for apt-get and yum
# shellcheck disable=SC2086
$maybe_sudo pganalyze-collector-setup $pgags_opts <$user_input
else
echo "Please continue with setup instructions in-app or at https://pganalyze.com/docs/install"
fi
19 changes: 17 additions & 2 deletions integration_test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ DOCKER_RUN_CMD = docker run --name pganalyze-collector-test \
-d \
pganalyze-collector-test

.PHONY: pg93 pg94 pg95 pg96 pg10 pg11 pg12 pg13 guided-setup
.PHONY: pg93 pg94 pg95 pg96 pg10 pg11 pg12 pg13 guided-setup installer

all: pg93 pg94 pg95 pg96 pg10 pg11 pg12 pg13 guided-setup
all: pg93 pg94 pg95 pg96 pg10 pg11 pg12 pg13 guided-setup installer

pg93:
docker build -f Dockerfile.test-pg93 $(DOCKER_BUILD_OPTS)
Expand Down Expand Up @@ -230,3 +230,18 @@ guided-setup:
exit 1; \
fi
diff -Nau guided-setup.snapshot-subset.json.expected guided-setup.snapshot-subset.json.out && echo 'success'

installer:
docker build -f Dockerfile.test-guided-setup $(DOCKER_BUILD_OPTS)
$(DOCKER_RUN_CMD)
sleep 10

docker exec --privileged pganalyze-collector-test env PGA_INSTALL_NONINTERACTIVE=true PGA_API_KEY=abc123 bash -c '</collector/contrib/install.sh bash' >install.out
docker rm -f pganalyze-collector-test
docker rmi pganalyze-collector-test

if ! grep -q 'The pganalyze collector was installed successfully' install.out; then \
echo "expected installer to install latest published package; test failed:"; \
cat install.out; \
exit 1; \
fi
7 changes: 5 additions & 2 deletions packages/repo/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ REPO_DIR=$(TMP_DIR)/repo

docker_clean = docker kill pga-collector-repo && docker rm pga-collector-repo && docker rmi -f pga-collector-repo

.PHONY: update_rpm_repo push_packages_release push_packages_latest
.PHONY: all download_repo upload_repo copy_install_script update_rpm update_deb

all: download_repo update_rpm update_deb upload_repo
all: download_repo update_rpm update_deb copy_install_script upload_repo

download_repo:
rm -rf $(REPO_DIR)
Expand All @@ -17,6 +17,9 @@ download_repo:
upload_repo:
aws s3 sync --acl public-read --cache-control no-cache $(REPO_DIR) s3://packages.pganalyze.com/

copy_install_script:
cp ../../contrib/install.sh $(REPO_DIR)/collector-install.sh

update_rpm:
cp $(TMP_DIR)/$(RPM_SYSTEMD_PACKAGE) .
docker build --build-arg VERSION=$(VERSION) -f Dockerfile.repo-rpm -t pga-collector-repo .
Expand Down

0 comments on commit b32a38e

Please sign in to comment.