Tomorrow 23th of April is Sant Jordi (Saint George), the patron of Catalonia, and the Catalan traditional celebration consist in this day women gifting a book to the men they love and men gifting a rose to the women they love.
I created a voucher for all my Python books, so, since during 23th of April you can acquire the four books per $10 USD in total.
I also started to block entire ranges of Ip’s from Digital Ocean, as many attacks come from Servers in their infrastructure.
Despite blocking tens of thousands of Ip Addresses, the number of visitors keep growing.
My Health
Thanks to my strict discipline I managed to recover super well and I’m healthier than before and guided by the satisfied doctors we removed two daily medicines.
I started a new medicine that is for the final phase of my recuperation, which doctors expect to be completely. In fact I’m much more healthier than I was before going to the hospital.
Humor
Will AI take the world?Sadly, true history. The responsibility to deliver is from all of us.
So, I was working on a project and i wanted to test how long a file can be.
The resources I checked, and also the Kernel and C source I reviewed, were pointing that effectively the limit is 255 characters.
But I had one doubt… given that Python 3 String are UTF-8, and that Linux encode by default is UTF-8, will I be able to use 255 characters length, or this will be reduced as the Strings will be encoded as UTF-8 or Unicode?.
So I did a small Proof of Concept.
For the filenames I grabbed a fragment of the translation to English of the book epic book “Tirant lo Blanc” (The White Knight), one of the first books written in Catalan language and the first chivalry novel known in the world. You can download it for free it in:
from carleslibs.fileutils import FileUtils
from colorama import Fore, Back, Style , init
class ColorUtils:
def __init__(self):
# For Colorama on Windows
init()
def print_error(self, s_text, s_end="\n"):
"""
Prints errors in Red.
:param s_text:
:return:
"""
print(Fore.RED + s_text)
print(Style.RESET_ALL, end=s_end)
def print_success(self, s_text, s_end="\n"):
"""
Prints errors in Green.
:param s_text:
:return:
"""
print(Fore.GREEN + s_text)
print(Style.RESET_ALL, end=s_end)
def print_label(self, s_text, s_end="\n"):
"""
Prints a label and not the end line
:param s_text:
:return:
"""
print(Fore.BLUE + s_text, end="")
print(Style.RESET_ALL, end=s_end)
def return_text_blue(self, s_text):
"""
Restuns a Text
:param s_text:
:return: String
"""
s_text_return = Fore.BLUE + s_text + Style.RESET_ALL
return s_text_return
if __name__ == "__main__":
o_color = ColorUtils()
o_file = FileUtils()
s_text = "In the fertile, rich and lovely island of England there lived a most valiant knight, noble by his lineage and much more for his "
s_text += "courage. In his great wisdom and ingenuity he had served the profession of chivalry for many years and with a great deal of honor, "
s_text += "and his fame was widely known throughout the world. His name was Count William of Warwick. This was a very strong knight "
s_text += "who, in his virile youth, had practiced the use of arms, following wars on sea as well as land, and he had brought many "
s_text += "battles to a successful conclusion."
o_color.print_label("Erasure Code project by Carles Mateo")
print()
print("Task 237 - Proof of Concep of Long File Names, encoded is ASCii, in Linux ext3 and ext4 Filesystems")
print()
print("Using as a sample a text based on the translation of Tirant Lo Blanc")
print("Sample text used:")
print("-"*30)
print(s_text)
print("-" * 30)
print()
print("This test uses the OpenSource libraries from Carles Mateo carleslibs")
print()
print("Initiating tests")
print("================")
s_dir = "task237_tests"
if o_file.folder_exists(s_dir) is True:
o_color.print_success("Directory " + s_dir + " already existed, skipping creation")
else:
b_success = o_file.create_folder(s_dir)
if b_success is True:
o_color.print_success("Directory " + s_dir + " created successfully")
else:
o_color.print_error("Directory " + s_dir + " creation failed")
exit(1)
for i_length in range(200, 512, 1):
s_filename = s_dir + "/" + s_text[0:i_length]
b_success = o_file.write(s_file=s_filename, s_text=s_text)
s_output = "Writing file length: "
print(s_output, end="")
o_color.print_label(str(i_length).rjust(3), s_end="")
print(" file name: ", end="")
o_color.print_label(s_filename, s_end="")
print(": ", end="")
if b_success is False:
o_color.print_error("failed", s_end="\n")
exit(0)
else:
o_color.print_success("success", s_end="\n")
# Note: up to 255 work, 256 fails
I tried this in an Ubuntu Virtual Box VM.
As part of my tests I tried to add a non typical character in English, ASCii >127, like Ç.
When I use ASCii character < 128 (0 to 127) for the filenames in ext3/ext4 and in a ZFS Pool, I can use 255 positions. But when I add characters that are not typical, like the Catalan ç Ç or accents Àí the space available is reduced, suggesting the characters are being encoded:
Ç has value 128 in the ASCii table and ç 135.
I used my Open Source carleslibs and the package colorama.
I’m Catalan. In 1936 the fascist military leaded by franco raised in arms against the elected government of the Spanish Republic. The Italian and nazi German fascist in power bombed the Catalan population. Hundreds of thousands of innocent citizens were assassinated and millions of Catalan and Spaniards had to exile. The sons of those that were ruling with the dictator have been insisting in naming it a “civil war”, but it was the military lead by a fascist, revolting against the legitimate Republic and ending a democracy.
The dictatorship lasted until 1975, when the dictator died in the bed. The effects of the repression never abandoned Catalonia, and nowadays in Catalonia people is still detained by the Spanish police for talking the Catalan language in front of them, and our Parliament decisions are cancelled by the Spanish courts, for example to force the exit of a President of Catalonia that they didn’t like, or to force the Catalan schools to teach 25% of the time in Spanish attacking the Catalan teaching system.
During WW2 millions of Jews were mass murdered, also people from all the nations were assassinated.
Russian population suffered a lot also fighting the nazis.
Now we have to see how Russia’s army is invading Ukraine and murdering innocent citizens.
That’s horrible.
I know Engineers from Ukraine. Those guys were doing great building wealthy based on knowledge and working well for companies across the world. Now these people are being killed or Engineers, amongst all the brave population, are arming themselves to fight the invasion. Shells destroy beautiful cities and population are starving, and young soldiers from both sides will never be seen again by their mothers.
Let music play in solidarity with Ukraine. First is a Catalan group. Second is a famous Irish band in this epic song dedicated to the brave International Brigades, volunteers that fought the fascism in Spain and in Catalonia trying to make a better world.
The Blog
I’ve updated the SSL Certificate. The previous one I bought was issued for two years, and I renewed as it was due to expire.
Honestly, my ego was flattered. It is a lot of reputation.
Although in the past I got an offer from another monstrously big editorial to publish world wide my book Python 3 Combat Guide and I also rejected, and an offer from a digital learning platform to create an interactive course from this same book.
I’ve rejected it again this time.
If you are curious, this is what I answered to them:
Hi XXXX,
I'm well, thank you. I hope you are doing well too.
Thanks for taking the time to explain your conditions to me.
I feel flattered by your editorial thinking about me. I respect your brand, as I mentioned, as I own several of your titles.
However, I have to refuse your offer.
Is not the first time an editor has offered to publish one or more of my books. For all over the world, with much higher economic expectations.
I'll tell you why I love being at LeanPub:
1- I own the rights. All of them.
2- I can publish updates, and my readers get them for free. As I add new materials, the value is maximized for my readers.
3- I get 80% of the royalties.
4- If a reader is not happy, they can return the book for 60 days.
5- I can create vouchers and give a discount to certain readers, or give for free to people that are poor and are trying to get a career in Engineering.
The community of readers are very honest, and I only got 2 returns. One of them I think was from an editorial that purchased the book, evaluated it, and they contacted me to publish it, and after I rejected they applied for the refund.
I teach classes, and I charge 125 EUR per hour. I can make much more by my side than the one time payment you offer. The compensation for the video seems really obsolete.
Also, I could be using Amazon self publishing, which also brings bigger margins than you.
So many thanks for your offer. I thought about it because of the reputation, but I already have a reputation. I've thousands of visits to my tech blog, and because of the higher royalties, even if I sell less books through LeanPub it is much more rewarding.
Thanks again and have a lovely day and rest of the week.
Best,
Carles
The provisioning in Amazon AWS through their SDK is a book I’m particularly proud, as it empowers the developers so much. And I provide source code so they can go from zero to hero, in a moment. Amazon should provide a project sample as I do, not difficult to follow documentation.
Teaching / Mentoring
As I was requested, I’ve been offering advice and having virtual coffees with some people that recently started their journey to become Software Engineers and wanted some guidance and advice.
It has been great seeing people putting passion and studying hard to make a better future for themselves and for their families.
I’ll probably add to the blog more contents for beginners, although it will continue being a blog dedicated to extreme IT, and to super cool Engineering skills and troubleshooting.
For my regular students I have a discord space where we can talk and they can meet new friends studying or working in Engineering.
Free Resources
This github link provides many free books in multiple languages:
Zoom can zoom the view. So if they are sharing their screen, and font is too small, you can give a relax to your eyes by using Zoom’s zoom feature. It is located in View.
My health
After being in the hospital in December 2021, with risk for my life, and after my incredible recuperation, I’ve got the good news that I don’t need anymore 2 of the 3 medicines I was taking in a daily basis. It looks well through a completely recovery thanks to my discipline, doing sport every day several times, and the fantastic Catalan doctors that are supporting me so well.
Since they found what was failing in me, and after the emergency treatments I started to sleep really well. All night. That’s a privilege that I didn’t have for long long time.
Humor
Sad but true history. How many super talented Engineers have been hired and then they were given a shitty laptop/workstation super slow? That happened to me when I was hired by Volkswagen IT: gedas. I was creating projects for very big companies and I calculated that I was wasting 2 hours of my time compiling. The computer did not had enough RAM and was using swap.
This is a very simple guide for beginners, to benefit from using this amazing Python IDE with Git.
You may think that it’s a bit difficult and why you should use it. The first reason I would tell is because it marks the errors, not just syntax errors also if you have typos or you forgot an import or you forgot to declare a variable, has autocomplete, will mark when you don’t follow standards, etc… If you want to be a professional, this is the tool that most Python professional developers and companies use.
Go to Jetbrains page and from there select Developer Tools and PyCharm.
If you don’t have Git installed, PyCharm will tell you in red, and will allow you to install it for you. It is a very convenient way to install it, specially if you use Windows.
In Ubuntu or Debian Linux installing git is so easy as typing from the Terminal:
sudo apt install git
If it’s your first time PyCharm will ask you for your credentials in Gitlab, so your username or email, and your password.
As it is you own new project and it’s empty, you can trust it. Hit Trust Project.
A window with tips will appear, you can close it.
As you see your project is empty. Only has a the default README.md file created by Gitlab.
Creating new Python files
On the top left, over the name of your project folder press with the Right button of the mouse and select New > Python File
Enter the name of the file, I choose helloworld and press Enter.
You will be asked if you want to add automatically the file to Git. This refers to your local Git repository. Say Yes and you will see the file changing from color Red, which means it is not added to the repository to Green. Green means that is added, but has never been committed.
Just add this line to helloworld.py
print("Hello World")
Note: I made a typo and I wrote “helloworl.py” instead of “helloworld.py”, I will show how to fix this later.
Now, press over the file name over the top left, with the Right button of the mouse, and select Run helloworl (In your case will be Run helloword)
Note: To be able to run a Python program, you need to have Python installed.
Note2: Do not start the name of your file by test as PyCharm will consider that you are writing Unit Testing Code, and will not show the option to run the code, but to run with pytest (if you have pytest framework installed).
And you see on the bottom how it worked and printed “Hello World”.
To rename the file you’ll click over it with the Right button of the mouse and select Refactor > Rename
Type the correct name, in my case “helloworld.py” and for the Scope select: Current File.
PyCharm is so powerful that can search for your entire project to see if other files are using that file and will update the code to reflect the file name change. By indicating Scope: Current File we are telling that the change affects only to this file, and by not marking Search for references and not marking Search in comments and strings you are indicating to PyCharm that it should not search in code and comments to update them with the new file. This option is really useful when you get more confident with programming.
Perfect. Now you want to commit the file to the repository and Push.
The first time PyCharm will ask you how people will know you, that is, your visible name in the Git History of Commits, and your email. You can mark to use these properties locally. This is basically because Git needs to know how to identify you. Consider that Git was created to work with Teams, so everybody should know who made what. Add your friendly name, like “Carles Mateo” and your email. I recommend you to check to use this info for Git globally (all the projects in your computer).
When you commit you’re expected to provide a Commit Message. As Git is used by teams, to work on the same code, try to explain briefly what your changes consisted on.
If you press Commit, you will see how helloworld.py is no longer in color green, now is black. This means that the file is up to date respect our local Git.
Go to the Main Menu and select Git > Push.
You’ll see a message in the bottom indicating that your code has been pushed to the repository.
Now, you can refresh your browser, and you’ll see the changes in Gitlab:
PyCharm vs VSCode
I got asked what are the advantage from PyCharm respect VSCode.
IMO the most powerful feat from PyCharm are the refactors, the code analysis showing errors, unused variables, integration with virtual environment, support for pytest and Code Coverage (the pro ver). This article very nicely compares both: https://t.co/67h4ZL6EGk 1/2
While VSCode has some great support for Python coding with the ‘Python’ plugin by Microsoft, PyCharm is truly designed for Python development and it shows.
The Unix Epoch is the time, in seconds, that has passed since 1970-01-01 00:00:00 UTC.
#!/usr/bin/env python3
#
# Date time methods
#
# Author: Carles Mateo
# Creation Date: 2019-11-20 17:23 IST
# Description: Class to return Date, datetime, Unix EPOCH timestamp
#
import datetime
import time
class DateTimeUtils:
def get_unix_epoch(self):
"""
Will return the EPOCH Time. For convenience is returned as String
:return:
"""
s_now_epoch = str(int(time.time()))
return s_now_epoch
def get_datetime(self, b_milliseconds=False):
"""
Return the datetime with miliseconds in format YYYY-MM-DD HH:MM:SS.xxxxx
or without milliseconds as YYYY-MM-DD HH:MM:SS"""
if b_milliseconds is True:
s_now = str(datetime.datetime.now())
else:
s_now = str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
return s_now
def main():
o_datetime = DateTimeUtils()
s_now_epoch = o_datetime.get_unix_epoch()
s_now_date = o_datetime.get_datetime()
print(s_now_epoch)
print(s_now_date)
main()
zpool watch is a small Python program for Linux workstations with graphical environment and ZFS, that checks every 30 seconds if your OpenZFS pools are Ok.
If a pool is not healthy, it displays a message in a window using tk inter.
Basically allows you to skip checking from the terminal zpool status continuously or to having to customize the ZED service to send an email and having to figure out how to it can spawn a window alert to the graphical system or what to do if the session has not been initiated.
carleslibs
Since last News from the Blog I’ve released carleslibs v.1.06, v.1.0.5 and v.1.0.4.
v.1.0.6 adds a new class OsUtils to deal with mostly-Linux Os tasks, like knowing the userid, the username, if it’s root, the distribution name and kernel version.
It also adds:
DatetimeUtils.sleep(i_seconds)
In v.1.0.5 I’ve included a new method for getting the Datetime in Unix Epoc format as Integer and increased Code Coverage to 95% for ScreenUtils class.
v. 1.0.4 contains a minor update, a method in StringUtils to escape html from a string.
It uses the library html (part of Python core) so it was small work to do for me to create this method, and the Unit Test for it, but I wanted to use carleslibs in more projects and adding it as core functionality, makes the code of these projects I’m working on, much more clear.
Minor refactors and adding more Code Coverage (Unit Testing), and protection in the code for division per zero when seconds passed as int are 0. (this was not an actual error, but is worth protecting the code just in case for the future)
Currently in Master there is a stable version of 0.8.9 mainly fixing https://gitlab.com/carles.mateo/ctop/-/issues/51 which was not detecting when CTOP was running inside a Docker Container (reporting Unable to decode DMI).
My Books
Docker Combat Guide
Added 20 new pages with some tricks, like clearing the logs (1.6GB in my workstation), using some cool tools, using bind mounts and using Docker in Windows from command line without activating Docker Desktop or WSL.
One of my SATA 2TB 2.5″ 5,400 rpm drive got damaged and so was generating errors, so that was a fantastic opportunity to show how to detect and deal with the situation to replace it with a new SATA 2TB 3.5″ 7,200 rpm and fix the pool.
The company sent me the Stein, which is sent to the employees that serve for two years, with a recognition and a celebration called “The Circle of Honor”.
Books purchased
I bought this book as often I discover new ways, better, to explain the things to my students.
Sometimes I buy books for beginners, as I can get explained what I want to do super fast and some times they teach nice tricks that I didn’t know. I have huge Django books, and it took a lot to finish them.
A simpler book may only talk about how to install and work with it under a platform (Windows or Mac, as instance) but it is all that I require as the command to create projects are the same cross platform.
For example, you can get to install and to create a simple project with ORM, connected to the database, very quickly.
Software
So I just discovered that Zoom has an option to draw in the shared screen, like Slack has. It is called Annotate. It is super useful for my classes. :)
Also discovered the icons in the Chat. It seems that not all the video calls accept it.
Hardware
As Working From Home I needed an scanner, I looked in Amazon and all of them were costing more than €200.
I changed my strategy and I bought a All-In-One from HP, which costed me €68.
So I’ll have a scanner and a backup printer, which always comes handy.
The nightmare started after I tried to connect it with Ubuntu.
Ubuntu was not recognizing it. Checking the manuals they force to configure the printer from an Android/iPhone app or from their web page, my understanding is for windows only. In any case I would not install the proprietary drivers in my Linux system.
Annoyed, I installed the Android application, and it was requesting to get Location permissions to configure it. No way. There was not possible to configure the printer without giving GPS/Location permissions to the app, so I cancelled the process.
I grabbed a Windows 10 laptop and plugged the All-in-one through the USB. I ran the wizard to search for Scanners and Printers and was not unable to use my scanner, only to configure as a printer, so I was forced to install HP drivers.
Irritated I did, and they were suggesting to configure the printer so I can print from Internet or from the phone. Thanks HP, you’ll be the next SolarWinds big-security-hole. I said no way, and in order to use the Wifi I have to agree to open that security door which is that the printer would be connected to Internet permanently, sending and receiving information. I said no, I’ll use only via USB.
Even selecting that, in order to scan, the Software forces me to create an account.
Disappointing. HP is doing very big stupid mistakes. They used to be a good company.
Since they stopped doing the drivers in Barcelona years ago, their Software and solutions (not the hardware) went to hell.
I checked the reviews in the App Store and so many people gave them 1 star and have problems… what a shame the way they created this solution.
This is a great Open Source, multi-platform editor, so I wanted to support the creator.
Security
Attacks: looking for exploits
This is just a sample of a set of attacks to the blog in a 3 minutes interval.
Another one this morning:
Now all are blocked in the Firewall.
This is a non stop practice from spammers and pirates that has been going on for years.
It was almost three decades ago, when I was the Linux responsible of an ISP, and I was installing a brand new Linux system connected to a service called “infovia”, at the time when Internet was used with dial-up and modems, and in the interval of time of the installation, it got hacked. I had the Ethernet connected. So then already, this was happening.
The morning I was writing this, I blocked thousands of offending Ip Addresses.
Protection solutions
I recommend you to use CloudFlare, is a CDN/Cache/Accelerator with DoS protection and even in its Free version is really useful.
Fun/Games
So I come with a game kind of Quiz that you can play with your friends, family or work colleagues working from home (WFH).
The idea is that the master shares screen and sound in Zoom, and then the rest connect to jackbox.tv and enter the code displayed on the master’s screen on their own browser, and an interactive game is started.
It is recommended that the master has two monitors so they can also play.
The games are so fun as a phrase appearing and people having to complete with a lie. If your friends vote your phrase, believing is true, you get points. If you vote the true answer, you get points too.
Very funny and recommendable.
Stuff
<humor>Skynet sent another terminator to end me, but I terminated it. Its processor lays exhibited in my home now</humor>
I bought a laminator.
It has also a ruler and a trimmer to cut the paper.
It was only €39 and I’ve to say that I’m very happy with the results.
It takes around 5 minutes to be ready, it takes to get to the hot-enough temperature, and feeds the pages slowly, around 50 secs a DIN-A4, but the results are worth the time.
I’ve protected my medical receipts and other value documents and the work was perfect. No bubbles at all. No big deal if the plastic covers are introduced not 100% straight. Even if you pass again an already plasticized document, all is good.
Fun
Databases
One of my friends sent me this image.
It is old, but still it’s fun. So it assumes the cameras of the parking or speed cameras, will OCR the plate to build a query, and that the code is not well protected. So basically is exploiting a Sql Injection.
Anybody working on the systems side, and with databases, knows how annoying are those potential situations.
from urllib import request
from bs4 import BeautifulSoup
s_url = "https://blog.carlesmateo.com/movies-i-saw/"
s_html = request.urlopen(s_url).read().decode('utf8')
o_soup = BeautifulSoup(s_html, 'html.parser')
o_title = o_soup.find('title')
print(o_title.string) # Prints the tag string content
# Another possible way
if o_soup.title is not None:
s_title = o_soup.title.string
else:
s_title = o_title.title
print(s_title)
Equitas Health helps thousands of HIV-positive in Ohio, Dayton and Columbus.
Thousands more are reached with our prevention, testing, and other services. We are excited about embracing our expanded mission as a strategic step to further that legacy and its reach by providing care for all – with a focus on a safe and open space and highest quality healthcare for the LGBTQ community and others who are medically underserved.
I did my donation following a post by Terra Field, a former colleague at Blizzard and later leading Netflix’s Trans *ERG, but I didn’t see that she organized a gofund campaign, so I donated again :)
As I saw that there is a lack of clarity in the articles about this theme.
I also provided two alternatives ways, one pure Python3 and the other Bash based (grep awk tr)
Books
The books I publish in LeanPub have two prices, the suggested price, which is the price I consider the right price for the book, and the minimum price, which is the minimum price I authorized a reader can pay to have it.
You can buy it for the minimum price. You know better than anyone your economy.
So when a reader buys one of my books for the suggested price, instead of the minimum price, it’s really showing how they appreciate may work.
So thanks for all the support and appreciation you show!. :)
One of the motives I chose Leanpub platform is because I think is fair. No DRM, no BS. And the reader can ask for a refund within 45 days if they don’t like the book. It also makes very happy seeing that I don’t have any refunds. I appreciate it as a token of the usefulness of my work. Thanks. :)
Updates to Docker Combat File book (v.16 2021-11-24)
I added a nice trick to reverse engineering the original Dockerfile from a running Image.
I also added another typical copy and paste error into the Troubleshoot section.
Automating and Provisioning Amazon AWS (EC2, EBS, S3, CloudWatch) with boto3 (Amazon’s SDK for Python 3) and Python 3 book
I’m writing a book about how to automate your Amazon AWS tasks using Amazon’s AWS Python 3 SDK boto3, provisioning new instances, stopping, starting, creating volumes, creating/deleting buckets in S3, uploading/downloading files from S3…
It is currently 20% completed. With 43 pages it shows EC2 section already.
I’ve working in carleslibs v.1.0.3. I added MenuUtils class, which allows to assemble menus super quickly, that execute the code referenced in the menu array. Ideal for building CLI applications very fast.
I also added KeyboardUtils class, which allows to ask the user for String within certain lengths allowing or not spaces and/or underscores, and ask user for Integer values within a certain min and max, having 0 for go back.
The plan is to release the new version of carleslibs as soon as I’ve tested it properly.
sudo apt install python2 python3 python3-pip
# Install boto for Python 2 for Ansible (alternative way if pip install boto doesn't work for you)
python2 -m pip install boto
# Install Ansible
sudo apt install ansible
If you want to use Dynamic Inventory
So you can use the Python 2 ec2.py and ec2.ini files, adding them as to the /etc/ansible with mask +x, to use the Dynamic Inventory.
Then use the calls inside the shell script, or assuming that the previous file was named credentiasl.sh use source credentials.sh
ec2.py is written in Python 2, so probably will fail for you as it is invoked by python and your default interpreter will be Python 3.
So edit the first line of /etc/ansible/ec2.py and add:
#!/bin/env python2
Once credentials.sh is sourced, then you can just invoke ec2.py to get the list of your Instances in a JSON format dumped by ec2.py
/etc/ansible/ec2.py --list
You can get that JSON file and load it and get the information you need, filtering by group.
You can call:
/etc/ansible/ec2.py --list > instances.json
Or you can run a Python program that escapes to shell and executes ec2.py –list and loads the Output as a JSON file.
I use my carleslibs here to escape to shell using my class SubProcessUtils. You can install them, they are Open Source, or you can code manually if you prefer importing subprocess Python library and catching the stdout, stderr.
import json
from carleslibs import SubProcessUtils
if __name__ == "__main__":
s_command = "/etc/ansible/ec2.py"
o_subprocess = SubProcessUtils()
i_error_code, s_output, s_error = o_subprocess.execute_command_for_output(s_command, b_shell=True, b_convert_to_ascii=True, b_convert_to_utf8=False)
if i_error_code != 0:
print("Error escaping to shell!", i_error_code)
print(s_error)
exit(1)
json = json.loads(s_output)
d_hosts = json["_meta"]["hostvars"]
for s_host in d_hosts:
# You'll get a ip/hostnamename in s_host which is the key
# You have to check for groups and the value for the key Name, in order to get the Name of the group
# As an exercise, print(d_hosts[s_host]) and look for:
# @TODO: Capture the s_group_name
# @TODO: Capture the s_addres
if s_group_name == "yourgroup":
# This filters only the instances with your group name, as you want to create an inventory file just for them
# That's because you don't want to launch the playbook for all the instances, but for those in your group name in the inventory file.
a_hostnames.append(s_address)
# After this you can parse you list a_hostnames and generate an inventory file yourinventoryfile
# The [ec2hosts] in your inventory file must match the hosts section in your yaml files
# You'll execute your playbook with:
# ansible-playbook -i yourinventoryfile youryamlfile.yaml
So an example of a yaml to install Apache2 in Ubuntu 20.04 LTS spawned instances , let’s call it install_apache2.yaml would be:
---
- name: Update web servers
hosts: ec2hosts
remote_user: ubuntu
tasks:
- name: Ensure Apache is at the latest version
apt:
name: apache2
state: latest
update_cache: yes
become: yes
As you can see the section hosts: in the YAML playbook matches the [ec2hosts] in your inventory file.
You can choose to have your private key certificate .pem file in /etc/ansible/ansible.cfg or if you want to have different certificates per host, add them after the ip/address in your inventory file, like in this example:
The first method is to use add_host to print in the screen the properties form the ec2 Instances provisioned.
The trick is to escape to shell, executing ansible-playbook and capturing the output, then parsing the text looking for the ‘public_ip:’
This is the Python 3 code I created:
class AwesomeAnsible:
def extract_public_ips_from_text(self, s_text=""):
"""
Extracts the addresses returned by Ansible
:param s_text:
:return: Boolean for success, Array with the Ip's
"""
b_found = False
a_ips = []
i_count = 0
while True:
i_count += 1
if i_count > 20:
print("Breaking look")
break
s_substr = "'public_ip': '"
i_first_pos = s_text.find(s_substr)
if i_first_pos > -1:
s_text_sub = s_text[i_first_pos + len(s_substr):]
# Find the ending delimiter
i_second_pos = s_text_sub.find("'")
if i_second_pos > -1:
b_found = True
s_ip = s_text_sub[0:i_second_pos]
a_ips.append(s_ip)
s_text_sub = s_text_sub[i_second_pos:]
s_text = s_text_sub
continue
# No more Ip's
break
return b_found, a_ips
Then you’ll use with something like:
# Catching the Ip's from the output
b_success, a_ips = self.extract_public_ips_from_text(s_output)
if b_success is True:
print("Public Ips:")
s_ips = ""
for s_ip in a_ips:
print(s_ip)
s_ips = s_ips + self.get_ip_text_line_for_inventory(s_ip)
print("Adding Ips to group1_inventory file")
self.o_fileutils.append_to_file("group1_inventory", s_ips)
print()
The get_ip_text_line_for_inventory_method() returns a line for the inventory file, with the ip and the key to use separated by a tab (\t):
def get_ip_text_line_for_inventory(self, s_ip, s_key_path="ansible.pem"):
"""
Returns the line to add to the inventory, with the Ip and the keypath
"""
return s_ip + "\tansible_ssh_private_key_file=" + s_key_path + "\n"
Once you have the inventory file, like this below, you can execute the playbook for your group of hosts:
You can run this Bash Shell Script to get only the public ips when you provision to Amazon AWS EC2 the Instances from your group named group1 in this case:
I set again the credentials because as this Bash Shell Script is invoked from Python, there are not sourced.
The trick in here is that the launch_aws_instances-group1.yaml file has a task to add the hosts to Ansible’s in memory inventory, and to print the information.
That output is what I scrap from Python and then I use extract_public_ips_from_text() showed before.
So my launch_aws_instances-group1.yaml (which I generate from Python customizing the parameter) looks like this:
In this case I use t1.micro cause I provision to EC2-Classic and not to the default VPC, otherwise I would use t2.micro.
So I have a Security Group named ansible created in Amazon AWS EC2 console as EC2-Classic, and not as VPC.
In this Security group I opened the Inbound HTTP Port and the SSH port for the Ip from I’m provisioning, so Ansible can SSH using the Key ansible.pem
The Public Key has been created and named ansible as well (section key_name under ec2).
The Image used is Ubuntu 20.04 LTS (free tier) for the region eu-west-1 which is my wonderful Ireland.
For the variables (vars) I use the MT Notation, so the prefixes show exactly what we are expecting s_ for Strings i_ for Integers and I never have collisions with reserved names.
It is very important to use the count_tag and instance_tags with the name of the group, as the actions will be using that group name. Remember the idempotency.
The task with the add_host is the one that makes the information for the instances to be displayed, like in this screenshot.
How big can be a variable (float, integer, string)
Operations performed, like +
MT Notation I use
The order in which the instructions are performed (top to bottom).
Declaring a variable
We can call thinks that were previously defined up (like functions)
Loops will send the execution pointer up
Operations with integer variables
Additions
Operations with Strings
Language syntax and tricks (write a Notebook with your own notes)
Pre-created solutions, like reverse an string with for
Open a file, read the contents by lines to string, split the strings to arrays by a separator, like tab or space, get what you want by position.
with open(s_filename) as file:
for s_line in file:
print(s_line)
# Show Exceptions
# Show hexadecimal of the text:
# cd /home/carles/Desktop/code/carles/python-classes/2021-11-11
# hexdump -c text.txt
# remove enters, spaces at the end of the file with s_line.rstrip()
The blocks and functions
Indentation
Typical error missing :
Functions are for reusing code and reducing errors
As they are for reusing, they are flexible (parameters)
The while loop
The condition True
The condition in a variable
The condition in a if
Break
Pattern counter inside a loop
Building a Menu for user selection in text mode
Input
Validation
Questions
As part of the questions, a question about the mental process to Build the solution was raised.
TODO: Was explained
The importance of keeping Notes with snippets of code that you normally use one time and another
How to search in Google to find explanations in Python sites
A question was raised about how menus could be implemented using OOP
A parent Menu class, with a MenuAdmin class inheriting was demonstrated. The MenuAdmin inherits the menu options from the parent Menu, and adds Admin only options.