41st Week of 2022
Activism⚑
Antifascism⚑
-
There are many ways to fight it, the book Todo el mundo puede ser Antifa: Manual practico para destruir el fascismo of Pol Andiñach gathers some of them.
One way we've seen pisses them off quite much is when they are ridiculed and they evocate the image of incompetence. It's a fine line to go, because if it falls into a pity image then it may strengthen their victim role.
Coding⚑
Languages⚑
Configure Docker to host the application⚑
-
New: Update dockers with Renovate.
Renovate is a program that does automated dependency updates. Multi-platform and multi-language.
-
New: Connect multiple docker compose files.
You can connect services defined across multiple docker-compose.yml files.
In order to do this you’ll need to:
- Create an external network with
docker network create <network name>
- In each of your
docker-compose.yml
configure the default network to use your externally created network with the networks top-level key. - You can use either the service name or container name to connect between containers.
- Create an external network with
Python Snippets⚑
-
New: Print datetime with a defined format.
now = datetime.now() today.strftime('We are the %d, %b %Y')
Where the datetime format is a string built from these directives.
-
New: Print string with asciiart.
pip install pyfiglet
from pyfiglet import figlet_format print(figlet_format('09 : 30'))
If you want to change the default width of 80 caracteres use:
from pyfiglet import Figlet f = Figlet(font="standard", width=100) print(f.renderText("aaaaaaaaaaaaaaaaa"))
-
New: Print specific time format.
datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
Code Meaning Example %a Weekday as locale’s abbreviated name. Mon %A Weekday as locale’s full name. Monday %w Weekday as a decimal number, where 0 is Sunday and 6 is Saturday. 1 %d Day of the month as a zero-padded decimal number. 30 %-d Day of the month as a decimal number. (Platform specific) 30 %b Month as locale’s abbreviated name. Sep %B Month as locale’s full name. September %m Month as a zero-padded decimal number. 09 %-m Month as a decimal number. (Platform specific) 9 %y Year without century as a zero-padded decimal number. 13 %Y Year with century as a decimal number. 2013 %H Hour (24-hour clock) as a zero-padded decimal number. 07 %-H Hour (24-hour clock) as a decimal number. (Platform specific) 7 %I Hour (12-hour clock) as a zero-padded decimal number. 07 %-I Hour (12-hour clock) as a decimal number. (Platform specific) 7 %p Locale’s equivalent of either AM or PM. AM %M Minute as a zero-padded decimal number. 06 %-M Minute as a decimal number. (Platform specific) 6 %S Second as a zero-padded decimal number. 05 %-S Second as a decimal number. (Platform specific) 5 %f Microsecond as a decimal number, zero-padded on the left. 000000 %z UTC offset in the form +HHMM or -HHMM (empty string if the the object is naive). %Z Time zone name (empty string if the object is naive). %j Day of the year as a zero-padded decimal number. 273 %-j Day of the year as a decimal number. (Platform specific) 273 %U Week number of the year (Sunday as the first day of the week) as a zero padded decimal number. All days in a new year preceding the first Sunday are considered to be in week 0. 39 %W Week number of the year (Monday as the first day of the week) as a decimal number. All days in a new year preceding the first Monday are considered to be in week 0. %c Locale’s appropriate date and time representation. Mon Sep 30 07:06:05 2013 %x Locale’s appropriate date representation. 09/30/13 %X Locale’s appropriate time representation. 07:06:05 %% A literal '%' character. %
ICS⚑
-
New: Introduce ICS.
ics is a pythonic iCalendar library. Its goals are to read and write ics data in a developer-friendly way.
rich⚑
-
New: Live display text.
import time from rich.live import Live with Live("Test") as live: for row in range(12): live.update(f"Test {row}") time.sleep(0.4)
If you don't want the text to have the default colors, you can embed it all in a
Text
object.
Selenium⚑
-
New: Click on element.
Once you've opened the page you want to interact with
driver.get()
, you need to get the Xpath of the element to click on. You can do that by using your browser inspector, to select the element, and once on the code if you right click there is a "Copy XPath"Once that is done you should have something like this when you paste it down.
//*[@id=”react-root”]/section/main/article/div[2]/div[2]/p/a
Similarly it is the same process for the input fields for username, password, and login button.
We can go ahead and do that on the current page. We can store these xpaths as strings in our code to make it readable.
We should have three xpaths from this page and one from the initial login.
first_login = '//*[@id=”react-root”]/section/main/article/div[2]/div[2]/p/a' username_input = '//*[@id="react-root"]/section/main/div/article/div/div[1]/div/form/div[2]/div/label/input' password_input = '//*[@id="react-root"]/section/main/div/article/div/div[1]/div/form/div[3]/div/label/input' login_submit = '//*[@id="react-root"]/section/main/div/article/div/div[1]/div/form/div[4]/button/div'
Now that we have the xpaths defined we can now tell Selenium webdriver to click and send some keys over for the input fields.
from selenium.webdriver.common.by import By driver.find_element(By.XPATH, first_login).click() driver.find_element(By.XPATH, username_input).send_keys("username") driver.find_element(By.XPATH, password_input).send_keys("password") driver.find_element(By.XPATH, login_submit).click()
-
New: Bypass Selenium detectors.
Sometimes web servers react differently if they notice that you're using selenium. Browsers can be detected through different ways and some commonly used mechanisms are as follows:
- Implementing captcha / recaptcha to detect the automatic bots.
- Non-human behaviour (browsing too fast, not scrolling to the visible elements, ...)
- Using an IP that's flagged as suspicious (VPN, VPS, Tor...)
- Detecting the term HeadlessChrome within headless Chrome UserAgent
- Using Bot Management service from Distil Networks, Akamai, Datadome.
They do it through different mechanisms:
- Use undetected-chromedriver
- Use Selenium stealth
- Rotate the user agent
- Changing browser properties
- Predefined Javascript variables
- Don't use selenium
If you've already been detected, you might get blocked for a plethora of other reasons even after using these methods. So you may have to try accessing the site that was detecting you using a VPN, different user-agent, etc.
DevOps⚑
Infrastructure as Code⚑
Gitea⚑
-
New: Introduce gitea.
Gitea is a community managed lightweight code hosting solution written in Go. It's the best self hosted Github alternative in my opinion.
Automating Processes⚑
renovate⚑
-
New: Introduce Renovate.
Renovate is a program that does automated dependency updates. Multi-platform and multi-language.
Why use Renovate?
- Get pull requests to update your dependencies and lock files.
- Reduce noise by scheduling when Renovate creates PRs.
- Renovate finds relevant package files automatically, including in monorepos.
- You can customize the bot's behavior with configuration files.
- Share your configuration with ESLint-like config presets.
- Get replacement PRs to migrate from a deprecated dependency to the community suggested replacement (npm packages only).
- Open source.
- Popular (more than 9.7k stars and 1.3k forks)
- Beautifully integrate with main Git web applications (Gitea, Gitlab, Github).
- It supports most important languages: Python, Docker, Kubernetes, Terraform, Ansible, Node, ...
Storage⚑
NAS⚑
-
New: Analyze RAM to buy.
Most ZFS resources suggest using ECC RAM. The provider gives me two options:
- Kingston Server Premier DDR4 3200MHz 16GB CL22
- Kingston Server Premier DDR4 2666MHz 16GB CL19
I'll go with two modules of 3200MHz CL22 because it has a smaller RAM latency.
-
New: Analyze motherboard to buy.
After reading these reviews(1, 2) I've come to the decision to purchase the ASRock X570M Pro4 because, It supports:
- 8 x SATA3 disks
- 2 x M.2 disks
- 4 x DDR4 RAM slots with speeds up to 4200+ and ECC support
- 1 x AMD AM4 Socket Ryzen™ 2000, 3000, 4000 G-Series, 5000 and 5000 G-Series Desktop Processors
- Supports NVMe SSD as boot disks
- Micro ATX Form Factor.
And it gives me room enough to grow:
- It supports PCI 4.0 for the M.2 which is said to be capable of perform twice the speed compared to previous 3rd generation. the chosen M2 are of 3rd generation, so if I need more speed I can change them.
- I'm only going to use 2 slots of RAM giving me 32GB, but I could grow 32 more easily.
-
New: Analyze CPU to buy.
After doing some basic research I'm between:
Property Ryzen 7 5800x Ryzen 5 5600x Ryzen 7 5700x Ryzen 5 5600G Cores 8 6 8 6 Threads 16 12 16 12 Clock 3.8 3.7 3.4 3.9 Socket AM4 AM4 AM4 AM4 PCI 4.0 4.0 4.0 3.0 Thermal Not included Wraith Stealth Not included Wraith Stealth Default TDP 105W 65W 65W 65W System Mem spec >= 3200 MHz >= 3200 MHz >= 3200 MHz >= 3200 MHz Mem type DDR4 DDR4 DDR4 DDR4 Price 315 232 279 179 The data was extracted from AMD's official page.
They all support the chosen RAM and the motherboard.
I'm ruling out Ryzen 7 5800x because it's too expensive both on monetary and power consumption terms. Also ruling out Ryzen 5 5600G because it has comparatively bad properties.
Between Ryzen 5 5600x and Ryzen 7 5700x, after checking these comparisons (1, 2) it looks like:
- Single core performance is similar.
- 7 wins when all cores are involved.
- 7 is more power efficient.
- 7 is better rated.
- 7 is newer (1.5 years).
- 7 has around 3.52 GB/s (7%) higher theoretical RAM memory bandwidth
- They have the same cache
- 7 has 5 degrees less of max temperature
- They both support ECC
- 5 has a greater market share
- 5 is 47$ cheaper
I think that for 47$ it's work the increase on cores and theoretical RAM memory bandwidth.
-
New: Analyze CPU coolers to buy.
It looks that the Ryzen CPUs don't require a cooler to work well. Usually it adds another 250W to the consumption. I don't plan to overclock it and I've heard that ZFS doesn't use too much CPU, so I'll start without it and monitor the temperature.
If I were to take one, I'd go with air cooling with something like the Dark Rock 4 but I've also read that Noctua are a good provider.
-
New: Analyze server cases to buy.
I'm ruling out the next ones:
- Fractal Design R6: More expensive than the Node 804 and it doesn't have hot swappable disks.
- Silverstone Technology SST-CS381: Even though it's gorgeous it's too expensive.
- Silverstone DS380: It only supports Mini-ITX which I don't have.
The remaining are:
Model Fractal Node 804 Silverstone CS380 Form factor Micro - ATX Mid tower Motherboard Micro ATX Micro ATX Drive bays 8 x 3.5", 2 x 2.5" 8 x 3.5", 2 x 5.25" Hot-swap No yes Expansion Slots 5 7 CPU cooler height 160mm 146 mm PSU compatibility ATX ATX Fans Front: 4, Top: 4, Rear 3 Side: 2, Rear: 1 Price 115 184 Size 34 x 31 x 39 cm 35 x 28 x 21 cm I like the Fractal Node 804 better and it's cheaper.
OpenZFS⚑
-
New: Choosing the cold spare disks.
It's good to think how much time you want to have your raids to be inconsistent once a drive has failed.
In my case, for the data I want to restore the raid as soon as I can, therefore I'll buy another rotational disk. For the SSDs I have more confidence that they won't break so I don't feel like having a spare one.
Hardware⚑
CPU⚑
-
New: Introduce CPU, attributes and how to buy it.
A central processing unit or CPU, also known as the brain of the server, is the electronic circuitry that executes instructions comprising a computer program. The CPU performs basic arithmetic, logic, controlling, and input/output (I/O) operations specified by the instructions in the program.
RAM⚑
-
New: Introduce RAM, it's properties and how to buy it.
RAM is a form of computer memory that can be read and changed in any order, typically used to store working data and machine code.
Operating Systems⚑
Linux⚑
i3wm⚑
-
New: Introduce i3wm.
i3 is a tiling window manager.
-
New: Layout saving.
Layout saving/restoring allows you to load a JSON layout file so that you can have a base layout to start working with after powering on your computer.
First of all arrange the windows in the workspace, then you can save the layout of either a single workspace or an entire output:
i3-save-tree --workspace "1: terminal" > ~/.i3/workspace-1.json
You need to open the created file and remove the comments that match the desired windows under the
swallows
keys, so transform the next snippet:... "swallows": [ { // "class": "^URxvt$", // "instance": "^irssi$" } ] ...
Into:
... "swallows": [ { "class": "^URxvt$", "instance": "^irssi$" } ] ...
Once is ready close all the windows of the workspace you want to restore (moving them away is not enough!).
Then on a terminal you can restore the layout with:
i3-msg 'workspace "1: terminal"; append_layout ~/.i3/workspace-1.json'
It's important that you don't use a relative path
Even if you're in
~/.i3/
you have to usei3-msg append_layout ~/.i3/workspace-1.json
.This command will create some fake windows (called placeholders) with the layout you had before,
i3
will then wait for you to create the windows that match the selection criteria. Once they are, it will put them in their respective placeholders.If you wish to create the layouts at startup you can add the next snippet to your i3 config.
exec --no-startup-id "i3-msg 'workspace \"1: terminal\"; append_layout ~/.i3/workspace-1.json'"
Khal⚑
-
New: Edit the events in a more pleasant way.
The
ikhal
event editor is not comfortable for me. I usually only change the title or the start date and in the default interface you need to press many keystrokes to make it happen.A patch solution is to pass a custom script on the
EDITOR
environmental variable. Assuming you havequestionary
andics
installed you can save the next snippet into anedit_event
file in yourPATH
:"""Edit an ics calendar event.""" import sys import questionary from ics import Calendar file = sys.argv[1] with open(file, "r") as fd: calendar = Calendar(fd.read()) event = list(calendar.timeline)[0] event.name = questionary.text("Title: ", default=event.name).ask() start = questionary.text( "Start: ", default=f"{str(event.begin.hour).zfill(2)}:{str(event.begin.minute).zfill(2)}", ).ask() event.begin = event.begin.replace( hour=int(start.split(":")[0]), minute=int(start.split(":")[1]) ) with open(file, "w") as fd: fd.writelines(calendar.serialize_iter())
Now if you open
ikhal
asEDITOR=edit_event ikhal
, whenever you edit one event you'll get a better interface. Add to your.zshrc
or.bashrc
:alias ikhal='EDITOR=edit_event ikhal'
The default keybinding for the edition is not very comfortable either, add the next snippet on your config: