Skip to content

Commit

Permalink
feat: perform basic package validation (#23863)
Browse files Browse the repository at this point in the history
* chore: remove unused build/ci scripts

* feat: validate packages during build

* chore: test CentOS aarch64 package

* fix: remove x86_64 from parameterized workflow

* fix: don't upgrade packages

Since some unrelated packages break during upgrade, this
no longer upgrades the system before installing
influxdb.
  • Loading branch information
bnpfeife committed Dec 1, 2022
1 parent 26daa86 commit 853d615
Show file tree
Hide file tree
Showing 14 changed files with 373 additions and 264 deletions.
68 changes: 68 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ nofork_filter: &nofork_filter
branches:
ignore: /pull\/[0-9]+/


workflows:
version: 2
build:
Expand Down Expand Up @@ -133,6 +134,22 @@ workflows:
exclude:
- { os: darwin, arch: arm64 }
- { os: windows, arch: arm64 }
- check_package_deb_amd64:
requires:
- build-package-linux-amd64
- check_package_deb_arm64:
requires:
- build-package-linux-arm64
- check_package_rpm:
<<: *nofork_filter
name:
check_package_rpm-<< matrix.arch >>
matrix:
parameters:
arch: [ x86_64, aarch64 ]
requires:
- build-package-linux-amd64
- build-package-linux-arm64
- test-downgrade:
<<: *any_filter
requires:
Expand Down Expand Up @@ -880,3 +897,54 @@ jobs:
root: .
paths:
- changelog_artifacts

check_package_deb_amd64:
machine:
image: ubuntu-2204:current
resource_class: medium
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Validate Debian Package (AMD64)
command: |
sudo .circleci/scripts/package-validation/ubuntu \
/tmp/workspace/artifacts/influxdb2*-amd64.deb
check_package_deb_arm64:
machine:
image: ubuntu-2204:current
resource_class: arm.medium
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Validate Debian Package (ARM64)
command: |
sudo .circleci/scripts/package-validation/ubuntu \
/tmp/workspace/artifacts/influxdb2*-arm64.deb
check_package_rpm:
parameters:
arch:
type: string
executor: linux-amd64
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Install Dependencies
command: |
sudo snap install --classic terraform
- add_ssh_keys:
fingerprints:
- "91:0a:5b:a7:f9:46:77:f3:5d:4a:cf:d2:44:c8:2c:5a"
- run:
name: Validate RPM Package
command: |
export AWS_ACCESS_KEY_ID=$TEST_AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$TEST_AWS_SECRET_ACCESS_KEY
.circleci/scripts/package-validation/centos << parameters.arch >> /tmp/workspace/artifacts/influxdb2*.<< parameters.arch >>.rpm
69 changes: 69 additions & 0 deletions .circleci/scripts/package-validation/centos
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash
set -o errexit \
-o nounset \
-o pipefail

# $1 -> architecture
# $2 -> package path
arch="${1}"
package="$(realpath "${2}")"

path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"

terraform_init() {
pushd "${path}/tf" &>/dev/null

# Unfortunately, CircleCI doesn't offer any RPM based machine images.
# This is required to test the functionality of the systemd services.
# (systemd doesn't run within docker containers). This will spawn a
# CentOS 9 Stream EC2 instance in AWS.
terraform init
terraform apply \
-auto-approve \
-var "architecture=${1}" \
-var "package_path=${2}" \
-var "identifier=${CIRCLE_JOB}"

popd &>/dev/null
}

terraform_free() {
pushd "${path}/tf" &>/dev/null

terraform destroy \
-auto-approve \
-var "architecture=${1}" \
-var "package_path=${2}" \
-var "identifier=${CIRCLE_JOB}"

popd &>/dev/null
}

terraform_ip() {
pushd "${path}/tf" &>/dev/null

terraform output -raw node_ssh

popd &>/dev/null
}


# This ensures that the associated resources within AWS are released
# upon exit or when encountering an error. This is setup before the
# call to "terraform apply" so even partially initialized resources
# are released.
# shellcheck disable=SC2064
trap "terraform_free \"${arch}\" \"${package}\"" \
SIGINT \
SIGTERM \
ERR \
EXIT

terraform_init "${arch}" "${package}"

printf 'Setup complete! Testing %s... (this takes several minutes!)' "${1}"

# Since terraform *just* created this instance, the host key is not
# known. Therefore, we'll disable StrictHostKeyChecking so ssh does
# not wait for user input.
ssh -o 'StrictHostKeyChecking=no' "ec2-user@$(terraform_ip)" 'sudo ./validate rpm ./influxdb2.rpm'
112 changes: 112 additions & 0 deletions .circleci/scripts/package-validation/tf/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 2.70"
}
}
}

variable "architecture" {
type = string
}

variable "identifier" {
type = string
}

variable "package_path" {
type = string
}

provider "aws" {
region = "us-east-1"
}

data "aws_ami" "centos" {
most_recent = true

# This information is sourced from https://wiki.centos.org/Cloud/AWS
# and should pull the latest AWS-provided CentOS Stream 9 image.
filter {
name = "name"
values = [format("CentOS Stream 9 %s*", var.architecture)]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["125523088429"]
}

resource "aws_security_group" "influxdb_test_package_sg" {
ingress {
description = "Allow ssh connection"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
description = "Allow all outgoing"
from_port = 0
to_port = 0
protocol = "all"
cidr_blocks = ["0.0.0.0/0"]
}
}

resource "aws_instance" "centos" {
count = 1
ami = data.aws_ami.centos.id
instance_type = var.architecture == "x86_64" ? "t2.micro" : "c6g.medium"
key_name = "circleci-oss-test"
vpc_security_group_ids = [aws_security_group.influxdb_test_package_sg.id]

tags = {
Name = format("circleci_%s_centos_%s", var.identifier, var.architecture)
}

provisioner "file" {
source = var.package_path
destination = "/home/ec2-user/influxdb2.rpm"

connection {
type = "ssh"
user = "ec2-user"
host = self.public_dns
agent = true
}
}

provisioner "file" {
source = "../validate"
destination = "/home/ec2-user/validate"

connection {
type = "ssh"
user = "ec2-user"
host = self.public_dns
agent = true
}
}

provisioner "remote-exec" {
inline = [
"chmod +x /home/ec2-user/validate",
]

connection {
type = "ssh"
user = "ec2-user"
host = self.public_dns
agent = true
}
}
}

output "node_ssh" {
value = aws_instance.centos.0.public_dns
}
8 changes: 8 additions & 0 deletions .circleci/scripts/package-validation/ubuntu
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -o errexit \
-o nounset \
-o pipefail

path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"

"${path}/validate" deb "${1}"
116 changes: 116 additions & 0 deletions .circleci/scripts/package-validation/validate
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/bin/bash
set -o errexit \
-o nounset \
-o pipefail

usage() {
cat <<'EOF'
usage: validate [type] [path]
Program:
This application performs sanity checks on the provided InfluxDB
package. InfluxDB should *not* be installed on the system before
running this application. This validates new installations and
performs specific checks relevant only to InfluxDB.
Options:
type Must be "deb" or "rpm". This option instructs the
application to use the package manager associated
with "type".
path Path to InfluxDB package to validate.
EOF
}

if [[ ! "${1:-}" ]] || [[ ! "${2:-}" ]]
then
(usage) && exit 1
fi
PACKAGE_TYPE="${1}"
PACKAGE_PATH="${2}"

install_deb() {
# When installing the package, ensure that the latest repository listings
# are available. This might be required so that all dependencies resolve.
# Since this needs to be run by CI, we supply "noninteractive" and "-y"
# so no prompts stall the pipeline.
export DEBIAN_FRONTEND=noninteractive
apt-get update
# "apt-get install" should be used instead of "dpkg -i", because "dpkg"
# does not resolve dependencies. "apt-get" requires that the package
# path looks like a path (either fullpath or prefixed with "./").
apt-get install -y binutils "$(realpath "${PACKAGE_PATH}")"
}

install_rpm() {
# see "install_deb" for "update"
yum update -y
yum install -y binutils
yum localinstall -y "$(realpath "${PACKAGE_PATH}")"
}

case ${PACKAGE_TYPE}
in
deb)
(install_deb)
;;
rpm)
(install_rpm)
;;
esac

if ! which influxd &>/dev/null
then
printf 'ERROR: Failed to locate influxd executable!\n' >&2
exit 2
fi

NEEDED="$(readelf -d "$(which influxd)" | (grep 'NEEDED' || true ))"

# shellcheck disable=SC2181
if [[ ${?} -ne 0 ]]
then
cat <<'EOF'
ERROR: readelf could not analyze the influxd executable! This
might be the consequence of installing a package built
for another platform OR invalid compiler/linker flags.
EOF
exit 2
fi

if [[ "${NEEDED:-}" ]]
then
cat <<'EOF'
ERROR: influxd not statically linked! This may prevent all
platforms from running influxd without installing
separate dependencies.
EOF
exit 2
fi

PIE="$(readelf -d "$(which influxd)" | (grep 'Flags: PIE' || true))"
if [[ ! "${PIE:-}" ]]
then
printf 'ERROR: influxd not linked with "-fPIE"!\n'
exit 2
fi

if ! systemctl is-active influxdb &>/dev/null
then
systemctl start influxdb
fi

for i in 0..2
do
if ! systemctl is-active influxdb &>/dev/null
then
printf 'ERROR: influxdb service failed to start!\n'
exit 2
fi
# Sometimes the service fails several seconds or minutes after
# starting. This failure may not propagate to the original
# "systemctl start <influxdb>" command. Therefore, we'll
# poll the service several times before exiting.
sleep 30
done

printf 'Finished validating influxdb!\n'
1 change: 0 additions & 1 deletion scripts/ci/changelog-commit.txt

This file was deleted.

Loading

0 comments on commit 853d615

Please sign in to comment.