The Camel Cometh


The Camel has come to Aspire.

I have worked in Perl on and off for about 16 years, now. I started working with it in 2010 by chance. I would learn that I didn’t even know of Perl’s existence until after it was considered a dead language. Along the way I’ve seen lots of signs of life in the ecosystem, but it’s scattered. On the spectrum of ghost town to thriving ecosystem, it certainly lives in the middle.

How many people reading this have ever even really used Perl? Your container images almost certainly resolve the command ‘perl -v’ unless you’ve opted specifically for one of the extreme lightweight distros - which is something I learned along the way.

I don’t blame people who call it a dead language.

Never forget: What is dead may never die.

With the preamble out of the way - I’ll be blunt: I didn’t choose to do this. I was baited into it.

When I first heard about Aspire, I was just excited to try it as a user. I was always annoyed at starting up individual apps when making an api with something else calling it. It was intriguing to do it in one “app.” I know there were other frameworks to be used, but I saw too much yaml and I hate secret key/value memorization tests and since it wasn’t forced upon me I just never worked much in distributed systems.

As I looked more into Aspire and saw a couple of other languages outside of dotnet, I happened to see that one of those was Python support and I got… flustered. My first professional job was in Python and I just can’t understand how it won the scripting language wars, I really liked Perl much more. It’s got a lot of nice things about it and the package management system is really solid when you consider it kinda started in 1995. I’ve been seeing Python become more official in the last several years - from being baked into Excel to getting official tabbed documentation throughout Microsoft Learn articles - it taunts me.

I had been lurking in the discord and ended up perusing the guide to making an integration which was pinned in the Discord’s #building-resources-and-integrations channel. Then I found out about the Community Toolkit which had a few of other languages supported, Go, Rust, and Java. So I got curious and began creating a Perl integration in September.

Looking back at the questions I was asking in the Discord I was attempting to start with perl as a container, because I still wasn’t quite understanding the full picture.

By October I was able to see Perl called via Aspire, but I was just scratching the surface. At this point, I’d gotten into looking around the Community Toolkit which exposed me to dev containers, which was a nice side quest.

Around November, Aspire did it a-damn-gain. With version 13, Python got top billing as a “First Class” crying and screaming language in the Aspire repo itself, along with a demo of debugging it.

Writing an integration was a nice way to learn more about Aspire internals, and I had no idea what I was getting myself into in late September when I started. I committed to trying to match Python’s “first-class” feature set with another language.

As I made progress, I kept banging my head up against Python features that ultimately were internal only at the time because Aspire used internal types / apis to let Python be an all-star.

I’m not jealous, please don’t write that I am jealous.

So at that point I felt I had a decent enough grasp of Resources / ContainerResources and I was starting to understand Annotations and Commands. Coincidentally around the same time work was pushing us towards using more AI so I also got a 10 dollar Copilot subscription for home.

I will spare you a big “I was wrong and agentic coding is awesome,” sidequest here - especially because I think it is losing subsidization and I’m not certain I could do this again - and just say that I started leveraging AI with great success. I had it compare what I currently had of the perl integration with the python integration and create a roadmap to get the perl integration to feature parity until I hit internal boundaries and then leave those as roadmap items.

This basically was the pathway for me to leverage my tiny 1-2 hour window of spare time after work and family time into something “useful” while making that experience pleasant.

Being able to use that roadmap to make the agent work in small chunks off of what I had built before to ensure I could code review smaller pieces at a time made it feel great and really stretched the memory muscles I built up learning the Aspire contribution guides.

I have successfully merged it to main in the Community Toolkit.

Big Learnings

Number 1: Dev Containers

I’d never had experience working with a dev container. I now have a decent amount of experience working with them and configuring them. The Community Toolkit is configured with one, and instead of fighting it I leaned into trying it. It was fairly simple to just get the extensions and let VS Code spin it up. That lead to playing with options and tweaking it to add things related to Perl. It was a great way to walk into an existing setup that works and come out of it understanding what various pieces of the devcontainer.json are doing and used for - not to mention how to shell out commands after the container builds.

Number 2: Github Actions

I’ve only ever used Azure Pipelines, and because I chose to integrate with the Community Toolkit I got a crash course in how to use Github Actions. I also learned that the official Github images for the Runners include Perl (even on Windows!) which was a nice treat to simplifying what I needed to get my integration tests working in the workflow.

Number 3: Perl kinda cooked with Package Management

CPAN, which you can read about on wikipedia, began development in 1993, and has been active for over 30 years now. It released in 1995!

Number 4: Some BRAVE soul made an OpenTelemetry SDK in Perl!

The biggest shout out to JJAtria for his work on the OpenTelemetry::SDK library! That really was what made the Perl Integration feel so much better with minimal effort. The hardest thing was figuring out exactly how to get it to build on Windows - an area of Perl that receives little love. I ultimately ended up making a full Windows developer setup guide which was immensely helpful in truly understanding more about how Perl works in general AND how to get OpenTelemetry working with the Google Protobuf libraries - even on Windows.

Number 5: Aspire has a TON of Uses

I think one of the coolest things I had an idea to do was, with a language like Perl that has a lot of dead zones in what it provides. For example, there’s no Azure SDK in Perl. There is the beginnings of one out there, but it is not fleshed out. Aspire allows us to use emulators in containers to run against. That means we could easily iterate with live integration tests against emulators of Key Vault or what have you in order to flesh out weak spots in the Perl ecosystem - even agentically.

You could just inject your library under development into an aspire app and point your scripts to use that library as you develop it. All languages could do this!

I think it is a godsend for local development tooling, with the agent getting eyes into what it’s building with the Aspire CLI / dashboard / resource logs, and with 13.3 it will have access to the browser logs, as well.

Is the marketing team happy? I said the phrase.

Summary

I have things about the integration that I already don’t like and will iterate against, but it’s made, it works, and it orchestrates perl projects. It is currently unable to be used without pulling the Community Toolkit down and packing the project manually, but on the next release, the package should be generally available for other people to try.

What it can do already:

  • It has the ability to use all 3 of the big package managers
  • You can model a script that runs once or as a service
  • You can model an API
  • You can add a separate perl environment
  • It has the ability to put out a dockerfile for the resource

There is more I want to do with it:

  • I want to add debugging
  • I want to create a package manager / package API instead of having the cute .WithCpanminus / .WithCarton methods..
  • I want to really get the publish docker file working
  • I would like to create a ContainerResource for it with sane defaults (for like worker services or apis).
  • I would like to equip it to work with Typescript apphosts.

I’ve got detailed documentation for how to use it over at the aspire.dev site here aspire.dev/integrations

I’ve made some samples - and will be continuing to add to them - you can view them at github.com/Omnideth/aspire-perl-examples

I’ll write more as I add more features!