Saturday, December 23, 2023

Baked potatoes

  • 4 to 6 Russet potatoes
  • Olive oil
  • Sea salt / kosher salt
  • Toppings: yogurt / sour cream, bacon, chives / green onions, salsa roja, cheese, etc

Preheat oven 425F.

Line a baking sheet with parchment paper.

Wash potatoes, dry, and poke with fork.

Coat potatoes with olive oil, sprinkle liberally with kosher / sea salt.

Bake at 425 for 40-60 minutes until 202F / 94C inside. Convection optional.

Meanwhile, prepare the toppings, e.g. bacon.

Slice open, fluff the insides, and add toppings.

References

https://www.loveandlemons.com/baked-potato/

https://blog.thermoworks.com/thermometer/the-dirt-on-potatoes/


Fake backstory

It was an ordinary evening when I stumbled upon a peculiar antique shop tucked away in a quiet corner of the city. Intrigued by the dusty books and peculiar artifacts, my eyes fell upon an old-looking oven with a brass plaque that read, "Potato Portal: Your Gateway to Culinary Time Travel."

The shop owner, a wizened man with a twinkle in his eye, noticed my interest and shared the tale of the magical baked potato oven. Legend had it that each perfectly baked potato could transport the eater to a different time and place.

Eager to test this extraordinary claim, I purchased the oven and a bag of russet potatoes. That evening, armed with a sense of adventure and a craving for the unknown, I prepared the potatoes with a mix of skepticism and excitement.

As the potatoes baked, the air in my kitchen seemed to shimmer. A soft glow emanated from the oven, and I couldn't help but wonder if I was about to embark on an unprecedented journey through time.

With a cautious fork, I pierced the crispy skin of one of the baked potatoes. As the steam rose, a sudden rush of warmth enveloped me, and the world around me blurred. When my vision cleared, I found myself in a bustling Victorian-era market, surrounded by horse-drawn carriages and people in corsets and top hats.

Stunned by the unexpected time travel, I roamed the cobbled streets, marveling at the sights and sounds of a bygone era. The aroma of roasted chestnuts and the clip-clop of horses' hooves filled the air. I couldn't believe that a humble baked potato had become a vessel through time.

After exploring the Victorian age, I returned to my kitchen, eager to share my extraordinary experience. I couldn't resist testing the Potato Portal once again, this time transporting myself to the Roaring Twenties. Flapper dresses, jazz music, and the vibrant energy of the era surrounded me as I enjoyed my second time-traveling adventure.

Word of my magical baked potatoes spread, and soon friends and neighbors gathered in my kitchen to experience the Potato Portal for themselves. Each potato became a ticket to a different time and place, creating a whimsical culinary time-travel club.

The once-ordinary oven had become a cherished artifact, and as we laughed and shared stories from different eras, it became clear that the magic of baked potatoes had not only transcended time but also brought people together in a delightful and unexpected way. The Potato Portal became a symbol of the extraordinary adventures that could unfold when a simple meal was seasoned with a dash of imagination.

Monday, December 18, 2023

Build clangd from source

Copied from https://jdhao.github.io/2021/07/03/install_clangd_on_linux/ because sometimes good things disappear from the 'net.

quote

git clone --depth=1 https://github.com/llvm/llvm-project.git

cd llvm-project
mkdir build && cd build
cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_INSTALL_PREFIX=~/tools/llvm -DCMAKE_BUILD_TYPE=Release ../llvm
make -j 16
make install

Some explanation about the options used:

  • -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra": it specifies which targets we want to build. To use clangd and clang-tidy, clang-tools-extra is a must.
  • -DCMAKE_INSTALL_PREFIX=~/tools/llvm: it specifies where we want to install llvm, in this case, we install it under ~/tools/llvm.
  • -DCMAKE_BUILD_TYPE=Release: it specifies the build type. Release type will be smaller than Debug.

For more details about Cmake options on building llvm, check here.

/quote

Thanks jdhao!

I need this because the work VMs use RHEL7 with no chance to upgrade (the project is built on this to support customers running RHEL7 and up), and I want to config neovim lsp with cpp support.

But wait there's more. This version of LLVM needs cmake 3.20 or higher and of course the VM only has cmake 2.8

- visit cmake.org/download and wget the source

- extract

./bootstrap --prefix=/usr/local
make -j8
sudo make install
 

And now GCC needs to be version 7.4 or newer, but the VM is running 4.8.5. Sigh.

 

Sunday, December 10, 2023

Dusting off this Blog

I was reminded about blogger by Irene and Man Yung's blog when I found their wonderful post about the har gow. I couldn't agree more about the dismal state of har gow in Toronto. It's 2023, and it seems like most dim sum is made at the same factory using the same recipes. Pretty sure I can back that up with a link, but that's a rabbit hole for another time. When Jane Squirrel makes har gow at home, the flavour is noticeably different from everyone else's. Better even, in many ways. The point is not to brag about how good we have it at our nest. It's more like... if anyone was actually making their own har gow using their own secret family recipe that's been passed down for generations, there would be more variety, right? Instead, so much of the har gow and shiu mai seem the same. Same flavour, same size, same shape. Pretty tasty when you're eating it, but indistinguishable and otherwise unremarkable.

Anyway, back to this blog and Blogger in general. When I saw Irene and Man Yung's blog, I was like "holy cow, people still use Blogger?". Hah, sorry Blogger, don't get mad.

So I had a poke around at my account, found bunch of cool old posts, some drafts (don't worry, you're not missing anything), and a bunch of worthless comments (screw you, spammers).

I want take this chance to reiterate that this blog has no affiliation with the Bob the Squirrel comic strip. Part of the reason I stopped posting was concern about being confused with that comic or its author. The squirrel this blog is named after lived in our backyard, and is part of many in-family jokes concerning, for example bitter melon. I wish the other Bob squirrel the best, and if you are in the mood please check them out.

With any luck, I will be posting more content. No promises.. seems every time I commit to doing something, there's no follow through. So, we'll see.

Sunday, January 22, 2017

Wrapup: Docker Developer - Beginner Linux Containers course

So, I did another quick run-through of the subject course this morning prior to taking the test, and here are my thoughts.

  • I'd forgotten about a few potentially useful commands like "docker inspect", so the review was useful.
  • Lesson 3 (docker-compose) still feels ... compressed. There could have been more content, or it could have been a complete course all by itself. The overall structure of the lesson was 1) download the files from git; 2) bring up the swarm; 3) a brief explanation of some of the lines in the yml file; and 4) here's how to publish the swarm. I would like to see the lesson expanded to get a better sense of how the yml file was developed step by step. In fact, the example included four other yml files, so that might have been where the direction the author(s) was (were) originally headed. Update: found the tutorial which this lesson appears to be a summary of: https://docs.docker.com/engine/getstarted-voting-app/
I scored 13/14 on the quiz, so yay me.

I'm going to take the rest of the free courses offered by Docker, just to see if they issues like resource control.

Saturday, January 21, 2017

More fun with the Docker Developer Beginner Linux Containers course

This time in lesson 3. Problems bringing up the docker swarm.

docker compose up -d

Only redis stayed up, according to docker ps -a. The other four containers exited prematurely.

First action: run compose up again without the -d option. This results in more output from each container. Summary of the output:

vote_1: python can't open file 'app.py': [Errno 13] Permission denied
worker_1: System.AggregationException: One or more errors occurred. (No such device or address)
db: exited with code 1

Well, after spending about a day debugging this, I found some comments on github that fedora uses a fork of docker, and the version may be out of date. So I uninstalled docker:

sudo dnf remove docker-engine docker-compose docker

Reinstalled from the official repos using instructions from:

https://docs.docker.com/engine/installation/linux/fedora/
https://docs.docker.com/compose/install/

And rebooted the machine because systemctl start docker-engine complained "docker-engine.service not found". After all this, the docker-compose tutorial worked as expected.

Here are some debugging notes, even if the correct solution ultimately turned out to be "reinstall from official sources."

As always, focus on one problem at a time. I did this by commenting out all but one member of the swarm in docker-compose.yml, and running "docker-compose up" to debug. The "command:" line in the yml file can be changed to try different things in the container. For example, replacing "command: python app.py" with "command: ls -l /" allowed me to see that the ownership of the app directory (1000:1000) did not match the user (root), which explains the permission denied error.

Learn how to clean up and run things manually.

docker ps # show running containers
docker ps -a # show all containers
docker rm <container id> # remove containers listed in docker ps -a
docker rm -f <container id>
docker images
docker rmi <image id> # remove images

A neat shortcut is you only need to pass the first three digits of a container or image id.

Note that running "docker run -it examplevotingapp_vote /bin/sh" produced different results (i.e. /app was owned by root instead of 1000). My guess is it's because the docker-compose.yml file has this line:

volumes:
  - ./vote:/app

This tells docker-compose to mount the "vote" directory in the cwd on the host as "/app". Of course, the vote directory is owned by me (uid 1000) instead of root, so that probably explains the ownership weirdness.

The difference from running the container manually and using docker-compose ultimately led me to realize that docker-compose starts up container examplevotingapp_vote_1. My current theory is that docker-compose takes the base _vote image and adds another layer to it according to the configuration in the yml file (e.g. mounts the /app volume, connects to the swarm networks, etc). Using layers is consistent with the docker architecture from what I've seen so far, so let's run with that for now.

One final note about the last build-push-pull steps from the end of the lesson. The steps do allow you to access (pull) your voting app containers from another machine. But they fail to mention what else you'll to bring up the swarm. Certainly, docker-compose up failed to do anything until I cloned the example app from github. And running docker-compose up now, it seems to be rebuilding the swarm instead of using the containers I already pulled down. And yes, docker images confirms there is now images beginning with examplevotingapp* as well as bobthesquirrel/votingapp*. Needs further investigation.

Thursday, January 19, 2017

Notes on Docker Course - Developer Beginner Linux Containers

I walked through the Developer Beginner Linux Containers course offered by Docker today, and hit a few snags. There's no obvious way to post comments or feedback to get the instructions updated, so here are my notes, for what they're worth.

Lesson 2.0 Webapps with Docker

This is the first snag:

$ sudo docker build -t bob_the_squirrel/myfirstapp .
[sudo] password for bob:
Sending build context to Docker daemon 8.192 kB
Step 1 : FROM alpine:latest
---> 88e169ea8f46
Step 2 : RUN apk add --update py-pip
---> Running in 15deabd22845
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz
ERROR: unsatisfiable constraints:
 py-pip (virtual):
   provided by: py2-pip
   required by: world[py-pip]
The command '/bin/sh -c apk add --update py-pip' returned a non-zero code: 1

Easily fixed by modifying the Dockerfile:

# install the pip package and any dependencies
RUN apk add --update py2-pip # the lesson says to use py-pip


The next snag was this:

$ sudo docker build -t bob_the_squirrel/myfirstapp .
[sudo] password for bob:
Sending build context to Docker daemon 8.192 kB
Step 1 : FROM alpine:latest
---> 88e169ea8f46
Step 2 : RUN apk add --update py2-pip
---> Running in 33207dfe8efd
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz
(1/12) Installing libbz2 (1.0.6-r5)
(2/12) Installing expat (2.2.0-r0)
(3/12) Installing libffi (3.2.1-r2)
(4/12) Installing gdbm (1.12-r0)
(5/12) Installing ncurses-terminfo-base (6.0-r7)
(6/12) Installing ncurses-terminfo (6.0-r7)
(7/12) Installing ncurses-libs (6.0-r7)
(8/12) Installing readline (6.3.008-r4)
(9/12) Installing sqlite-libs (3.15.2-r0)
(10/12) Installing python2 (2.7.13-r0)
(11/12) Installing py-setuptools (29.0.1-r0)
(12/12) Installing py2-pip (9.0.0-r0)
Executing busybox-1.25.1-r0.trigger
OK: 61 MiB in 23 packages
---> 840b9af43db6
Removing intermediate container 33207dfe8efd
Step 3 : COPY requirements.txt /usr/src/app
---> 0eac1e0f7a53
Removing intermediate container e9c368692b72
Step 4 : RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt
---> Running in cd9acc93e4f3
Could not open requirements file: [Errno 20] Not a directory: '/usr/src/app/requirements.txt'
You are using pip version 9.0.0, however version 9.0.1 is available.


You should consider upgrading via the 'pip install --upgrade pip' command. 


The command '/bin/sh -c pip install --no-cache-dir -r

/usr/src/app/requirements.txt' returned a non-zero code: 1

Turns out this was my fault because I forgot to add a trailing slash to the Dockerfile COPY command:

# Add files that make up the Flask application
COPY requirements.txt /usr/src/app # oops
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt


If the trailing slash is included (/usr/src/app/), it looks like the COPY command will make the directory if it doesn't already exist.

Sunday, January 6, 2013

OS By Petzl - Mixed Results

Tried using the OS By Petzl software on a Core battery connected to a Tikka XP2:

  • The software doesn't work on my x220 tablet running Windows 7 (64-bit): it fails to detect that the battery is plugged in.
  • Even after trying to run the software in various Windows Compatibility modes (Vista, XP SP2, XP SP3, Windows 7).
  • It does work on another computer which is running Windows XP: can name the battery, tell it which lamp is being used, and set profiles.
  • But I can't create a custom profile. The instructions are just plain wrong.
  • Maybe a conflict with Lenovo drivers? Who knows.

Lessons learned:

  • If I had been using Windows 7 System Restore, it would have saved me a lot of trouble trying to uninstall the Petzl software and drivers.
  • Restoring from a previous backup (Windows 7 Backup and Restore) works fine, and only took about 90 minutes.
  • Was also able to use Areca to restore user documents. (Right-click on an archive, choose "Recover...", and choose a recovery option.)
  • Drag and drop of a VMWare Player Linux VM to/from a USB drive worked fine as a way to backup it up.

So, be warned. The OS By Petzl software kinda sorta works, but don't count on it. Bet the battery controller could be hacked though.