diff --git a/.gitignore b/.gitignore index 3efe28a99..a72a0ca51 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ __pycache__ /containers/config/ /bin /rpmbuild + +/tools/appsre-ansible/inventory diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 871c6067a..ec92f9a18 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -92,11 +92,11 @@ Packer: stage: test extends: .terraform rules: - - if: '$CI_PIPELINE_SOURCE != "schedule"' + - if: '$CI_PIPELINE_SOURCE != "schedule" && $CI_COMMIT_BRANCH =~ /PR-[0-9]+/' script: - - schutzbot/packer.sh + - tools/appsre-build-worker-packer.sh variables: - RUNNER: aws/centos-stream-8-x86_64 + RUNNER: aws/rhel-8.5-ga-x86_64 Prepare-rhel-internal: stage: prepare-rhel-internal diff --git a/distribution/Dockerfile-ubi-packer b/distribution/Dockerfile-ubi-packer new file mode 100644 index 000000000..9ca246051 --- /dev/null +++ b/distribution/Dockerfile-ubi-packer @@ -0,0 +1,10 @@ +FROM registry.access.redhat.com/ubi8/ubi-minimal:latest + +RUN curl --location --output /etc/yum.repos.d/hashicorp.repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo +RUN microdnf install packer jq openssh-clients unzip rsync python3 rust cargo gcc python3-devel openssl-devel +RUN pip3 install setuptools-rust +RUN pip3 install ansible +RUN ansible-galaxy collection install ansible.posix +RUN curl https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip -o /tmp/awscli.zip +RUN unzip /tmp/awscli.zip +RUN aws/install diff --git a/schutzbot/packer.sh b/schutzbot/packer.sh deleted file mode 100755 index 054c79e38..000000000 --- a/schutzbot/packer.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -# Colorful output. -function greenprint { - echo -e "\033[1;32m[$(date -Isecond)] ${1}\033[0m" -} - -greenprint "📦 Installing epel" -sudo dnf install -y epel-release - -greenprint "📦 Installing hashicorp repo" -sudo curl --location --output /etc/yum.repos.d/hashicorp.repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo - -greenprint "📦 Installing packages needed for this script" -sudo dnf install -y packer ansible jq - -greenprint "🖼️ Building the image" - -export PKR_VAR_aws_access_key="$PACKER_AWS_ACCESS_KEY_ID" -export PKR_VAR_aws_secret_key="$PACKER_AWS_SECRET_ACCESS_KEY" -export PKR_VAR_image_name="osbuild-composer-worker-$CI_COMMIT_BRANCH-$CI_COMMIT_SHA" -export PKR_VAR_composer_commit="$CI_COMMIT_SHA" - -# use osbuild commit from Schutzfile -PKR_VAR_osbuild_commit=$(jq -r '.["rhel-8.4"].dependencies.osbuild.commit' Schutzfile) -export PKR_VAR_osbuild_commit - -packer build templates/packer diff --git a/templates/packer/ansible/roles/common/tasks/packages.yml b/templates/packer/ansible/roles/common/tasks/packages.yml index 5893e649b..13c34da8e 100644 --- a/templates/packer/ansible/roles/common/tasks/packages.yml +++ b/templates/packer/ansible/roles/common/tasks/packages.yml @@ -1,6 +1,8 @@ --- - name: Add osbuild-composer repository + tags: + - rpmrepo yum_repository: name: "composer" description: "osbuild-composer commit {{ COMPOSER_COMMIT }}" @@ -10,6 +12,8 @@ priority: "5" - name: Add osbuild repository + tags: + - rpmrepo yum_repository: name: "osbuild" description: "osbuild commit {{ OSBUILD_COMMIT }}" @@ -42,7 +46,6 @@ package: name: - jq - - osbuild-composer-worker - unzip - monit - vector @@ -74,3 +77,48 @@ loop: - /tmp/awscli.zip - /tmp/aws + +- name: Create rpmbuild directory + tags: + - rpmcopy + file: + path: "{{ item }}" + state: directory + with_items: + - /tmp/rpmbuild + - /tmp/rpmbuild/RPMS + +- name: Push rpms + tags: + - rpmcopy + ansible.posix.synchronize: + mode: push + src: "{{ playbook_dir }}/roles/common/files/rpmbuild/RPMS" + dest: /tmp/rpmbuild + +- name: Add repo config + tags: + - rpmcopy + copy: + dest: /etc/yum.repos.d/osbuild.repo + content: | + [osbuild] + name=osbuild + baseurl=file:///tmp/rpmbuild/RPMS + enabled=1 + gpgcheck=0 + priority=100 + +- name: Install worker rpm + package: + name: + - osbuild-composer-worker + state: present + +- name: Cleanup rpmbuild dir + file: + path: "{{ item }}" + state: absent + with_items: + - /tmp/rpmbuild + - /etc/yum.repos.d/osbuild.repo diff --git a/templates/packer/composer.pkr.hcl b/templates/packer/composer.pkr.hcl index f7c066a68..8ca9fbbff 100644 --- a/templates/packer/composer.pkr.hcl +++ b/templates/packer/composer.pkr.hcl @@ -39,7 +39,6 @@ source "amazon-ebs" "image_builder" { # Network configuration for the instance building our image. associate_public_ip_address = true - security_group_ids = ["sg-04bbbb35"] ssh_interface = "public_ip" ssh_username = "ec2-user" instance_type = "c5.large" @@ -50,9 +49,11 @@ build { provisioner "ansible" { playbook_file = "${path.root}/ansible/playbook.yml" + user = "ec2-user" extra_arguments = [ "-e", "COMPOSER_COMMIT=${var.composer_commit}", "-e", "OSBUILD_COMMIT=${var.osbuild_commit}", + "--skip-tags", "${var.ansible_skip_tags}", ] } } diff --git a/templates/packer/variables.pkr.hcl b/templates/packer/variables.pkr.hcl index 78b3177c4..2f2f2237f 100644 --- a/templates/packer/variables.pkr.hcl +++ b/templates/packer/variables.pkr.hcl @@ -15,3 +15,9 @@ variable "osbuild_commit" { type = string } # The name of the resulting AMI and the underlying EBS snapshot variable "image_name" { type = string } + +# Skip ansible tags +variable "ansible_skip_tags" { + type = string + default = "" +} diff --git a/tools/appsre-ansible/rpmbuild.yml b/tools/appsre-ansible/rpmbuild.yml new file mode 100644 index 000000000..9a2f6b9f3 --- /dev/null +++ b/tools/appsre-ansible/rpmbuild.yml @@ -0,0 +1,101 @@ +--- +- name: Build osbuild rpms + become: yes + remote_user: ec2-user + hosts: rpmbuilder + tasks: + + - name: Add EPEL + dnf: + name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + state: present + disable_gpg_check: yes + + - name: Upgrade all packages + package: + name: "*" + state: latest + register: result + retries: 5 + until: result is success + + - name: Create rpmbuild directory + file: + path: "{{ item }}" + state: directory + with_items: + - /tmp/rpmbuild + - /tmp/rpmbuild/SOURCES + - /tmp/rpmbuild/RPMS + + - name: Download osbuild-composer archive + get_url: + url: "https://github.com/osbuild/osbuild-composer/archive/{{ COMPOSER_COMMIT }}.tar.gz" + dest: "/tmp/rpmbuild/SOURCES/osbuild-composer-{{ COMPOSER_COMMIT }}.tar.gz" + + - name: Download osbuild-composer spec + get_url: + url: "https://raw.githubusercontent.com/osbuild/osbuild-composer/{{ COMPOSER_COMMIT }}/osbuild-composer.spec" + dest: /tmp/osbuild-composer.spec + + - name: Download osbuild archive + get_url: + url: "https://github.com/osbuild/osbuild/archive/{{ OSBUILD_COMMIT }}.tar.gz" + dest: "/tmp/rpmbuild/SOURCES/osbuild-{{ OSBUILD_COMMIT }}.tar.gz" + + - name: Download osbuild spec + get_url: + url: "https://raw.githubusercontent.com/osbuild/osbuild/{{ OSBUILD_COMMIT }}/osbuild.spec" + dest: /tmp/osbuild.spec + + - name: Install build tools + package: + name: + - rpm-build + - mock + - createrepo_c + state: present + + - name: Make osbuild srpm + command: >- + rpmbuild -bs + --define "commit {{ OSBUILD_COMMIT }}" + --define "_topdir /tmp/rpmbuild" + --define "_srpmfilename %%{NAME}.srpm" + /tmp/osbuild.spec + + - name: Mockbuild osbuild + shell: >- + mock + --rebuild + --define "commit {{ OSBUILD_COMMIT }}" + --define "_rpmfilename %%{NAME}.rpm" + --resultdir /tmp/rpmbuild/RPMS + /tmp/rpmbuild/SRPMS/osbuild-*.src.rpm + + - name: Make osbuild-composer srpm + command: >- + rpmbuild -bs + --define "commit {{ COMPOSER_COMMIT }}" + --define "_topdir /tmp/rpmbuild" + --define "_srpmfilename %%{NAME}.srpm" + /tmp/osbuild-composer.spec + + + - name: Mockbuild osbuild-composer + shell: >- + mock + --rebuild + --define "commit {{ COMPOSER_COMMIT }}" + --define "_rpmfilename %%{NAME}.rpm" + --resultdir /tmp/rpmbuild/RPMS + /tmp/rpmbuild/SRPMS/osbuild-composer-*.src.rpm + + - name: Create a repository from the artifacts + command: createrepo_c /tmp/rpmbuild/RPMS + + - name: Fetch rpms + ansible.posix.synchronize: + mode: pull + src: /tmp/rpmbuild/RPMS + dest: /osbuild-composer/rpmbuild diff --git a/tools/appsre-build-worker-packer.sh b/tools/appsre-build-worker-packer.sh new file mode 100755 index 000000000..4e42e5c1d --- /dev/null +++ b/tools/appsre-build-worker-packer.sh @@ -0,0 +1,150 @@ +#!/bin/bash +# AppSRE runs this script to build an ami and share it with an account +set -exv + + +COMMIT_SHA=$(git rev-parse HEAD) +COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + +# Use CI variables if available +if [ -n "$CI_COMMIT_SHA" ]; then + COMMIT_SHA="$CI_COMMIT_SHA" +fi +if [ -n "$CI_COMMIT_BRANCH" ]; then + COMMIT_BRANCH="$CI_COMMIT_BRANCH" +fi + +if [[ "$CI" == true ]]; then + sudo dnf install -y podman jq +fi + +# decide whether podman or docker should be used +if which podman 2>/dev/null >&2; then + CONTAINER_RUNTIME=podman +elif which docker 2>/dev/null >&2; then + CONTAINER_RUNTIME="docker --config=$PWD/.docker" +else + echo No container runtime found, install podman or docker. + exit 2 +fi + +function greenprint { + echo -e "\033[1;32m[$(date -Isecond)] ${1}\033[0m" +} + +KEY_NAME=$(uuidgen) +function cleanup { + if [[ "$CI" != true ]]; then + if [ -n "$AWS_INSTANCE_ID" ]; then + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 terminate-instances \ + --instance-ids "$AWS_INSTANCE_ID" + fi + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 delete-key-pair --key-name "$KEY_NAME" + fi + + $CONTAINER_RUNTIME rmi "packer:$COMMIT_SHA" +} +trap cleanup EXIT + +function ec2_rpm_build { + RPMBUILD_DIR="./templates/packer/ansible/roles/common/files/rpmbuild/RPMS" + mkdir -p "$RPMBUILD_DIR" + + greenprint "🚀 Start RHEL Cloud Access image to build rpms on" + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 create-key-pair \ + --key-name "$KEY_NAME" \ + --query 'KeyMaterial' \ + --output text \ + > ./keypair.pem + chmod 600 ./keypair.pem + + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 run-instances \ + --image-id ami-0b0af3577fe5e3532 --instance-type c5.large \ + --key-name "$KEY_NAME" \ + --tag-specifications "ResourceType=instance,Tags=[{Key=commit,Value=$COMMIT_SHA},{Key=name,Value=rpm-builder-$COMMIT_SHA}]" \ + > ./rpminstance.json + AWS_INSTANCE_ID=$(jq -r '.Instances[].InstanceId' "rpminstance.json") + + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 wait instance-running \ + --instance-ids "$AWS_INSTANCE_ID" + + $CONTAINER_RUNTIME run --rm \ + -e AWS_ACCESS_KEY_ID="$PACKER_AWS_ACCESS_KEY_ID" \ + -e AWS_SECRET_ACCESS_KEY="$PACKER_AWS_SECRET_ACCESS_KEY" \ + -e AWS_DEFAULT_REGION="us-east-1" \ + "packer:$COMMIT_SHA" aws ec2 describe-instances \ + --instance-ids "$AWS_INSTANCE_ID" \ + > "instances.json" + RPMBUILDER_HOST=$(jq -r '.Reservations[].Instances[].PublicIpAddress' "instances.json") + + + for LOOP_COUNTER in {0..30}; do + if ssh-keyscan "$RPMBUILDER_HOST" > /dev/null 2>&1; then + break + fi + echo "sleeping, try #$LOOP_COUNTER" + sleep 10 + done + + cat > tools/appsre-ansible/inventory <