Ruby: Waiting for one of multiple threads to finish

We build a small project that watches multiple metrics until one of them finds something, I found ThreadsWait in the stdlib and it was easy to use it. Also added error re-raising so the threads do not die silently and cleanup.

require 'thwait'

def wait_for_first_block_to_complete(*blocks)
  threads = blocks.map do |block|
    Thread.new do
      block.call
    rescue StandardError
      $!
    end
  end
  waiter = ThreadsWait.new(*threads)
  value = waiter.next_wait.value
  threads.each(&:kill)
  raise value if value.is_a?(StandardError)
  value
end

wait_for_first_block_to_complete(
  -> { sleep 1 }, -> { sleep 1 }
) # will stop after 1 second

 

Reading journald kernel logs from inside a kubernetes pod

We wanted a watcher that alerts us when bad kernel things happen and were able to deploy that as a DaemonSet using Kubernetes ūüôā

  • Use a Debian base image (for example ruby:2.5-stretch)
  • Run as root user or as user that can read systemd logs like¬†systemd-journal
  • Mount /var/run
    spec:
      containers:
      - name: foo
        ...
        volumeMounts:
        - name: runlog
          mountPath: /run/log
          readOnly: true
      volumes:
      - name: runlog
        hostPath:
          path: /run/log
  • Use¬†systemd-journal to read the logs
    require 'systemd/journal'
    journal = Systemd::Journal.new
    journal.seek(:tail)
    journal.move_previous
    journal.filter(syslog_identifier: 'kernel')
    journal.watch { |entry| puts entry.message }

Running multiple commands in docker in parallel

Went through foreman/goreman/forego and all of them either did not:
– support not printing the name
– support killing all when one finishes
– support sending signals to all children

But this does:

## Install parallel with `done` support
RUN \
  curl -sL http://ftp.gnu.org/gnu/parallel/parallel-20180422.tar.bz2 > /tmp/parallel.tar.bz2 && \
  cd /tmp && tar -xvjf /tmp/parallel.tar.bz2 && cd parallel* && \
  ./configure && make install && rm -rf /tmp/parallel*

# stream output and stop all commands if any of them finish/fail
parallel --no-notice --ungroup --halt 'now,done=1' {1} ::: 'sleep 10' 'sleep 20'

Chef install google-cloud-sdk without package manager

A tiny chef snipped to install gcloud without using a package manager (to get the latest version without waiting)

gcloud_version = node["foo"]["google-cloud-sdk_version"]
gcloud_file = "google-cloud-sdk-#{gcloud_version}-linux-x86_64.tar.gz"
gcloud_folder = "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads"
gcloud_installer = "https://dl.google.com/dl/cloudsdk/channels/rapid/install_google_cloud_sdk.bash"
execute "gcloud_install" do
  # clean up ... download installer but select the version we want ... install ... link
  command "rm -rf $CLOUDSDK_INSTALL_DIR/google-cloud-sdk && curl #{gcloud_installer} | sed 's;__SDK_URL_DIR=.*;__SDK_URL_DIR=#{gcloud_folder};' | sed 's/__SDK_TGZ=.*/__SDK_TGZ=#{gcloud_file}/' | bash && ln -sf $CLOUDSDK_INSTALL_DIR/google-cloud-sdk/bin/gcloud /usr/local/bin/gcloud"
  env(
    "CLOUDSDK_CORE_DISABLE_PROMPTS" => "true",
    "CLOUDSDK_INSTALL_DIR" => "/opt", # prefix
  )
  not_if { `true && gcloud -v`.include?(gcloud_version) } # ~FC048
end