❌

Reading view

There are new articles available, click to refresh the page.

11ty, nunjucks, tag counts

As I write more for the 100DaysToOffload, I like to post on my social media the post number. I also made this page for myself to review the posts I’ve written, and post counts. Initially I did not have this added on this page, but it is on my tags page where I list the tag and the number of posts in it.

On my tags page, it uses an eleventy filter of the collection of all posts, and adds this information to the collection. Then on the tags page do a for loop to loop through all the tags and post counts with Nunjucks.

config.addCollection("tagList", collection => {
    const tagsObject = {}
    collection.getAll().forEach(item => {
      if (!item.data.tags) return;
      item.data.tags
        .filter(tag => !['post', 'all'].includes(tag))
        .forEach(tag => {
          if(typeof tagsObject[tag] === 'undefined') {
            tagsObject[tag] = 1
          } else {
            tagsObject[tag] += 1
          }
        });
    });

    const tagList = []
    Object.keys(tagsObject).forEach(tag => {
      tagList.push({ tagName: tag, tagCount: tagsObject[tag] })
    })
  return tagList.sort((a, b) => b.tagCount - a.tagCount)
});

This is great, but I have a simpler collection of the posts by tags using the collectionApi.getFilteredByTag() filter.

// Get only content that matches a tag
config.addCollection("offload", function(collectionApi) {
  return collectionApi.getFilteredByTag("100DaysToOffload").reverse();
});

So now on my page specificly for the 100DaysToOffload, we can do a for loop to display just the posts in this collection.

Get IP From DNS Name Using Python

  Updated Plop Automation 2.0

  Human Readable File Sizes in PowerShell

  Reverse, esreveR

  Switch Python to Match

  Too Much Data

  Confirming public GPG fingerprints from Git platforms

  AWS EC2 termination protection

  Burning musical memories

  100 Pics - Day 9

  Securing 11ty with SSL Locally

  100 Pics - Day 8

  Adding GPG to Codeberg From Windows

  Codeberg Migration

  Jellyfin and SSL

  Be Proud of Your Work

  Blog Questions Challenge 2025

  Changing Your LUKS Full Disk Encryption Password

  How to tag AWS EBS volumes on Linux EC2 Servers

  100 Pics - Day 1

  Reviewing 2024

  Year in Review

  Updating Codeberg Pages Static Sites

  Expanding URLs in Powershell

  Automation waiting game

  The Collection

  Mobile writing, part 2

  Getting into Podcasts

  Using PSCustomObjects

  Backing up the Cloud

  Future proofing scripts

  The state of Linux

  Making Notepad with HTML

  Updating Docker Containers

  Advent of Code - Day 4

  Changing Git config URL

  Advent of Code - Day 1

  Wordle Analytics - November 2023

  Reducing the noise

  Making Change

  Knowing the long way

  Write fast, deploy, update

  Migrating 2FA apps

  Hardware and Tech I Use

  Do you follow RSS?

  GNOME VS KDE

  Almost there - 100DaysToOffload

  Download latest file from a S3 Bucket

  Posting from my phone

  Default apps

  Git Status

  Lessons learned, backup

  Installing Node.js on Pop!_OS 22.04 LTS

  Wordle Analytics - October 2023

  Using ChatGPT wisely

  Simple HTTP Server

  My Linux Journey

  Regex a UNC path

  TinaCMS + 11ty

  Verifying Ubuntu 23.10.1 ISO

  Updating Umami Analytics

  Taking A Screenshot In Python

  100 Days to Offload Update

  Network Usage Since Last Boot

  Hosting FreshRSS on Fly.io

  Robots and AI

  File Encryption with GPG

  Retro Gaming

  Creating a Test File

  Wordle Analytics - September 2023

  Using Cheat sheets

  Creating Status Pages on the Fly

  Scheduling Automatic Builds with Static Site Generators

  Boto3 cross regions for AWS Lambda Functions

  Building a Blogroll with 11ty

  Adding some flare to RSS

  List Throttling with Python

  Migrating GPG keys to a new machine

  Installing Node.js on Fedora

  CloudCannon + Eleventy

  The Good Side of Analytics - Umami & Vercel

  Wordle Analytics - August 2023

  Manage AWS Instances

  Wordle Analytics - July 2023

  I Broke NextCloud, Again

  What is in Your Headers?

  Wordle Analytics - June 2023

  Mapping the internet

  Wordle Analytics

  Finding your Windows Install Date

  Powershell GUI with WPF

  Ubuntu's change with Python support

  Bookmarks in PowerShell

  Console Speech API, Part 2

  Console Speech API and Beeps

  Spring Cleaning

  Getting Into Cron Jobs

  Intro to Pickleball

  Using the Codeberg CI

  How I Missed Gaming

  Using Cloudflare Workers to Get Visitor Information

  Select-Object with PowerShell

  Command Line vs GUI Windows programs

  Plop in Automation

  Extracting Files with Progress

  Port Checking in Python

  Creating a static site using Python and Flask

  Going Headless

  Nextcloud Docker Compose

  11ty, nunjucks, tag counts

  Adding a basic search to a static site

  Getting started with docker and Luanti (Minetest)

  GitHub profile with actions

  Website redesign with 11ty!

  Quick tips on Linux aliases

  How to start coding

  Securing Jekyll with SSL locally

  Got Git?

  Netlify hosting and redirects

  Working with Tags in Jekyll

  New Year's Resolution for 2023

This solution does not have a built in way to get the tag count. So I found two solutions that work in this situation.

Solution 1

Using the full tags collection. For this to work, we need to loop over all the tags, and if we find the tag we want, pull out the tagCount that is defined in our collection.

<h1>100 Days To Offload
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
</h1>

Depending on how many tags you have you’d still have to loop over all of them to pull out the one. This is a collection that is more of an array of the data that would be needed in one object.

Solution 2

The second method uses a variable and a loop as well to increase a count, then output that count.

<h1>100 Days To Offload
  
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
  <small>(121 posts)</small>
</h1>

I like this method as I have already filtered the tag in a collection, and manually added the count on the page at render time. This is a collection that just has the posts and basic information and not the extra details that could be included.

Wrap up

Both methods do work and could still have a valid use case when needed. My tags page has its own loop process to notate the tag name and tag counts. Now as I post more to the 100DaysToOffload, I can know the post counts. The 100DaysToOffload page uses the simpler collection and a for loop to get the data that is needed. On this page, I’d rather call back to the same collection, than call a larger collection to get a smaller amount of data.

When I moved from Jekyll and talked about the 11ty redesign, I had a post about the same process in Jekyll and working with tags


Reply via email

Year in Review

Not only is this the Year in Review for 2023, but it also completes the 100 Days to Offload challenge I started this time last year.

I wrote about 29 total tags and topics throughout the year.

Here's a neat graph by Robb Knight as well, similar to the GitHub commit graph. This is showing all the posts tagged for the 100 Days to Offload, which should be all posts from 2023 as well. There's that one post in 2022 for the start of journey.

2022

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec


2023

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec


2025

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec


Next, I thought it would be neat to list out the tags and the count of posts per tag to see the topics I wrote about.

This has been an exciting year! I have written a lot about my adventures of Docker, powershell, a new position and learning more about AWS. Upgrading my blog to use the 11ty backend static site generator. I think was the best choice this year to help add to the fun of writing and experimenting with the static site generator.

What is in store for next year? I have not decided if I will partake in the 100 Days to Offload again right now, but I have found a new groove in writing and keeping things updated. I still like writing about the new things I learn while coding and preparing my solutions. Writing things down this year has been helpful, and I have even gone back to my own posts later one to see how I did something as it also applied to a new issue.

Here’s to 2024!


Reply via email

Get IP From DNS Name Using Python

Python is a wonderful tool and known for its networking capabilities. It is one of the things that drew me to Python initially many years ago. There are a few ways Python allows someone to query and lookup network related tasks. Entire built-in modules and community modules have become the standard for looking up things like DNS requests.

I was needing to do a bulk DNS lookup and needed a no dependency way to get this information.

Using a DNS Module

There is a DNS module to query a few more DNS records besides just the IP address. First you will need to install the module.

pip install dnspython

Now for some magic!

import dns.resolver

hostname = "claytonerrington.com"

# Finding A record
result = dns.resolver.resolve(hostname, 'A')

# Printing record
for val in result:
    print(f"A Record : {val.to_text()}"

A Record : 76.76.21.164
A Record : 66.33.60.35

The dnspython module is a great choice for many DNS related tasks. To get just the known IPs of an address, this might be a little more than needed to install the module and get going.

Using Sockets

Python’s built-in module socket has a wide range of uses. A simple command to get the IP from a hostname; either computer or web address.

import socket

hostname = "claytonerrington.com"
ip_address = socket.gethostbyname(hostname)
print(f"A Record : {ip_address}")

A Record : 76.76.21.241

Great, I got the IP address my website is using! But wait… I know my website is using a load balancer and that typically has two or more IPs in the result. the gethostbyname() function will return the first address it gets in the response. There is an additional function that will return the entire response.

import socket
ip_address = socket.gethostbyname_ex(hostname)
print(f"A Record : {ip_address}")
print(f"A Record : {ip_address[2]}")

A Record : ('claytonerrington.com', [], ['76.76.21.241', '76.76.21.22'])
A Record : ['76.76.21.241', '76.76.21.22']

This is a tuple of the response. The documentation says it best:

Return a 3-tuple (hostname, aliaslist, ipaddrlist) where hostname is the host’s primary host name, aliaslist is a (possibly empty) list of alternative host names for the same address, and ipaddrlist is a list of IPv4 addresses for the same interface on the same host (often but not always a single address). gethostbyname_ex() does not support IPv6 name resolution, and getaddrinfo() should be used instead for IPv4/v6 dual stack support.

What is unique depending on the information you are after is the response this returns. If I were to test my subdomain of www.claytonerrington.com we will see the hostname and alias list filled out in this request.

A Record : ('cjerrington.vercel.app', ['www.claytonerrington.com'], ['76.76.21.241', '76.76.21.22'])

Advanced Sockets

When using sockets the gethostbyname() does return the IPv4 addresses, but we can use getaddrinfo() to get the IPv6 addresses. Depending on your needs this can be useful. I was needing to create an allow list based on a DNS entry and I wanted to know all the information in one request.

The process below takes our host name and looks for any socket addresses for any address family: IPv4, IPv6, or any other. This is defined by the family argument and specifying socket.AF_UNSPEC. Then with the results we look at the family type and add it to a list. If the list is populated with values, we then print this to the screen.

def get_dns_info(hostname):
  try:
      results = socket.getaddrinfo(hostname, None, socket.AF_UNSPEC)
      ipv4_addresses = []
      ipv6_addresses = []

      for result in results:
        family, _, _, _, sockaddr = result
        address = sockaddr[0]
 
        if family == socket.AF_INET:
          ipv4_addresses.append(address)
        elif family == socket.AF_INET6:
          ipv6_addresses.append(address)

      print(f"DNS information for '{hostname}':")
      if len(ipv4_addresses) > 0:
        print("IPv4 addresses:")
        for ipv4_address in set(ipv4_addresses):
          print(ipv4_address)

      if len(ipv6_addresses) > 0:
        print("\nIPv6 addresses:")
        for ipv6_address in set(ipv6_addresses):
          print(ipv6_address)
  except socket.gaierror as e:
      print(f"Error: Unable to resolve '{hostname}': {e}")

get_dns_info(hostname)


DNS information for 'claytonerrington.com':
IPv4 addresses:
76.76.21.241
76.76.21.22

Wrap up

The solutions today are pretty simple for the task at hand. The responses you get can easily be used for other processes like logging or checking an older value and alerting if an IP has changed. Hopefully this helps you in some basic networking topics.

Depending on the request, you can use gethostbyname() if just one IP is needed, and gethostbyname_ex() for all the known results. These examples used web site DNS names, but the same approach can be used for local host names as well.

Try using these concepts and ideas to build your own nslookup type script. What other possibilities could you use this for?


Reply via email

❌