From 30b0acaba65aa95bee257cb46b76ddc7d8071a1b Mon Sep 17 00:00:00 2001 From: Veronika Gnilitska <30597968+gberenice@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:51:00 +0200 Subject: [PATCH] fix: avoid RPM lock issue (#44) ## what This: * Removes unnecessary `sudo` commands since the [user-data script runs as the root user](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-shell-scripts). * Adds waiting for the RPM lock to be released. * We've seen the following logs during an instance start-up: ```sh user-data: RPM: error: can't create transaction lock on /var/lib/rpm/.rpm.lock (Resource temporarily unavailable) user-data: The downloaded packages were saved in cache until the next successful transaction. user-data: You can remove cached packages by executing 'yum clean packages'. user-data: Error: Could not run transaction. ``` * RPM database lock is being held by another process when script attempts to run yum/dnf commands. Amazon Linux 2023 (AL2023) may perform automatic updates or other package management tasks during boot, causing the RPM database to be locked temporarily. * Uses `dnf` instead of yum: Amazon Linux 2023 [uses dnf as the default package manager](https://docs.aws.amazon.com/linux/al2023/ug/package-management.html). `dnf` is the successor to `yum`. ## why * Prevents RPM lock issue and follows AWS recommended practices. ## references * N/A ## Summary by CodeRabbit - **New Features** - Updated script for Tailscale installation and configuration, improving efficiency with a retry mechanism for command execution. - **Bug Fixes** - Removed unnecessary `sudo` calls for a cleaner execution process. - **Documentation** - Enhanced readability of the `ssm_state_enabled` variable description in the configuration file. --- userdata.sh.tmpl | 48 ++++++++++++++++++++++++++++++++++++++---------- variables.tf | 4 +++- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/userdata.sh.tmpl b/userdata.sh.tmpl index e78c721..727bce9 100644 --- a/userdata.sh.tmpl +++ b/userdata.sh.tmpl @@ -4,23 +4,51 @@ exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>& echo "Starting user-data script..." echo "Enabling IP forwarding..." -echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf -echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf -sudo sysctl -p /etc/sysctl.conf +echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf +echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf +sysctl -p /etc/sysctl.conf + +# Function to retry a command up to a maximum number of attempts +retry_command() { + local cmd="$1" + local max_attempts="$2" + local attempt=1 + local exit_code=0 + + while [ $attempt -le $max_attempts ]; do + echo "Attempt $attempt of $max_attempts: $cmd" + eval "$cmd" + exit_code=$? + if [ $exit_code -eq 0 ]; then + echo "Command succeeded: $cmd" + return 0 + else + echo "Command failed with exit code $exit_code: $cmd" + attempt=$((attempt + 1)) + if [ $attempt -le $max_attempts ]; then + echo "Retrying in 2 seconds..." + sleep 2 + fi + fi + done + + echo "Command failed after $max_attempts attempts: $cmd" + return $exit_code +} echo "Installing Tailscale..." -sudo yum install -y yum-utils -sudo yum-config-manager --add-repo https://pkgs.tailscale.com/stable/amazon-linux/2/tailscale.repo -sudo yum install -y tailscale +retry_command "dnf install -y dnf-utils" 5 +retry_command "dnf config-manager --add-repo https://pkgs.tailscale.com/stable/amazon-linux/2/tailscale.repo" 5 +retry_command "dnf install -y tailscale" 5 %{ if tailscaled_extra_flags_enabled == true } echo "Exporting FLAGS to /etc/default/tailscaled..." -sudo sed -i "s|^FLAGS=.*|FLAGS=\"${tailscaled_extra_flags}\"|" /etc/default/tailscaled +sed -i "s|^FLAGS=.*|FLAGS=\"${tailscaled_extra_flags}\"|" /etc/default/tailscaled %{ endif } -# Setup tailscale +# Setup Tailscale echo "Enabling and starting tailscaled service..." -sudo systemctl enable --now tailscaled +systemctl enable --now tailscaled echo "Waiting for tailscaled to initialize..." sleep 5 @@ -28,7 +56,7 @@ sleep 5 # Start tailscale # We pass --advertise-tags below even though the authkey being created with those tags should result # in the same effect. This is to be more explicit because tailscale tags are a complicated topic. -sudo tailscale up \ +tailscale up \ %{ if ssh_enabled == true }--ssh%{ endif } \ %{ if exit_node_enabled == true }--advertise-exit-node%{ endif } \ %{ if tailscale_up_extra_flags_enabled == true }${tailscale_up_extra_flags}%{ endif } \ diff --git a/variables.tf b/variables.tf index 509e9ec..3d4f298 100644 --- a/variables.tf +++ b/variables.tf @@ -202,7 +202,9 @@ variable "ssm_state_enabled" { default = false type = bool description = <<-EOT - Control if tailscaled state is stored in AWS SSM (including preferences and keys). This tells the Tailscale daemon to write + read state from SSM, which unlocks important features like retaining the existing tailscale machine name. + Control if tailscaled state is stored in AWS SSM (including preferences and keys). + This tells the Tailscale daemon to write + read state from SSM, + which unlocks important features like retaining the existing tailscale machine name. See more in the [docs](https://tailscale.com/kb/1278/tailscaled#flags-to-tailscaled). EOT }