Previous Work Projects

Below are some projects that I have done throughout my career.

Image automation gone wild (Click to Expand)

During my time in Mass Storage, we were working to expand our customerbase by providing our OS images in as many formats as possible; This included expanding to virtualization, and cloud offerings, from baremetal only. When I joined, baremetal was the only option, built by hand, with vmware images being built by hand from the image we built for baremetal, for development only.

Using a combination of Ansible, Packer and bash script, I designed a complete imaging process. Using the internal ISO that the platform team developed and Ansible, I created an automatic installation and 'golden image' image prep process. This required installing on a specific baremetal configuration, and tracking the installation steps through reboots. At the end of this process, the systems disks were packed up as raw images for distribution to manufacturer for baremetal systems. Using more Ansible, this golden image was then transcribed to a VMWare image, for development use, and later to OVF (via Packer) for customer distribution. This golden image was additionally used via Packer to create images in AWS, GCP, and Azure.

Unfortunately because to the chosen distribution method of the base golden image, as a requirement of the manufacturer, the Packer process quickly became very un-packer-like. The AWS Packer module provided the ability to do chroot installations, which worked very well for us. However, neither GCP or Azure modules provided this capability. As a result, I wrote a number of bash scripts that mimicked the AWS chroot installation, for the other platforms. These bash scripts were fairly bulletproof, but were not built in a way that easily allowed changes. Thankfully the only changes that might have been required are cloud parameter changes, and the actual operations were standardized across all platforms.

Mass Merge Requests (Click to Expand)

AKA: How to make a whole development team shriek in terror

Throughout much of my career, Ive discovered the pros and cons of both using, and not using a monorepo. In one particular case, I encountered a platform using many repositories, and then building them together via dependencies. This might not have been terrible, except there were 50 repositories for what amounted to 3 applications. Each of these repositories was one library or another, or even the application itself. Each of them required a build process, and that build process was 99% the same across every single one of them. As I began to work on standardizing a build process, I realized that every repository had a copy of a build process from some other module. Unfortunately, every build process was copied from a random module, and that module may have gotten changes, and those changes not propagated to everything else, resulting in 50 unique build processes that did not need to be unique.

Once I had a unified build process, I needed to update every single repository with this new build process. That meant 50 merge requests. After a night of thinking on how awful that would be, I decided to spend a few days writing something to perform a scripted change, commit and merge using minimal manual touching. I ended up with 3 scripts (though they could've been combined into a single script), which would ingest a list of repositories, a script, a branch name, and a commit message. The first script would take the repository list and clone each one, create a branch, and change to that branch. The second script would take the user-provided script, and run it against repository. This script could either be a one-line command on the prompt, or, a prepared script with many actions. Finally, the last script would commit, push, and create a merge request.

I revealed this tool, and my intent to use it one day, as a part of resolving the mess of tech debt that had built up in the build system. There was no actual audio, but I certainly heard the shrieking of 20 developers as they realized the power of this tool. They were very wary of it, and the damage it could cause. Despite their silent screaming, I was able to convince them of its usefulness, and demonstrated its capability on a few repositories to prove it to them. Once on board, some of the developers started to ask if they could use it, and how it worked; allowing for mass amounts of repetitive work to be completed in just seconds. What would have taken me 6 months to get through (50 merge requests, with code reviews, etc) was cut down to 3 days of scripting, and 3 days of getting developers to approve the merges.

'Complete' Personal Projects

Below are some projects that I have worked on and can be viewed / used.

These are considered complete / active.

ArgStruct Specification (Click to Expand)

This is a project that attempts to unify the bridge between API and cli, using a single reusable argument structure. This structure is extendable to allow for additional special arguments based on need. Additionally, this same structure can be used to automatically generate documentation about each command / API endpoint.

The accompanying project provides a python library for interacting with ArgStruct, and generating documentation via commandline.

Much of this idea was spurred from the constant rebuilding of the same thing every time I wanted to build some API and also have a cli tool for that API. And as a part of this, I also built a tool called Specker, which is library that allows you to build a 'spec' file, and then compare structured data against that spec, while also setting default values, validating type, limiting input (such as specific values), etc.

This is an open specification which I hope others will use to alleviate the problem of replicating / pairing cli args to api calls. Also hoping to get input to better formulate the specification.

View Project

You Cant Change That! (Click to Expand)

This project came after many years of working some sort of support, from hosting to DevOps. Users gonna be users. Every once in a while (sometimes many onces in a while), a user will accidentally destroy their system through chown / chmod. This service is intended to provide a set of guardrails for such users. The service monitors specified files / directories for changes to their permissions, attributes, and/or content, and on change, alerts the user, then restores the content.

This started as I realized there really wasnt much that provided such functionality in the linux world, and also, sort of rightfully so. If you dont know what you're doing, you're gonna have a bad time when you accidentally chmod your entire /etc directory. At the same time, I am surprised that there arent some guardrails protecting critical files.

The service queries the specified files for their permissions/attributes/content, and saves it to a state file. Periodically, the service will check the file for changes, and then restore from known if there has been any changes. Changes can be made by disabling monitoring of a file/directory, changing the file, and then updating the state db. Content is compared by SHA256 sum, which means that content monitoring can be expensive, but is available.

View Project

Convection - Secrets, IaC (Click to Expand)

This project is partially complete.

This is a project where I am attempting my own take on tools like Vault, Ansible, Packer, and, Terraform. The end goal is to have a complete suite of automation tools for building, deploying, and maintaining any type of infrastructure. Additionally, I have some gripes with Hashi Vault, and others, which prompted me to write a secrets manager as a part of this suite.

Secrets Manager

The Secrets Manager has been completed, and is operational. It has not been validated by a security expert. It uses Fernet encryption to provide a rotation key set for each.

One particular design decision in the Secrets Manager, is authentication. The system uses pub/priv key pairs to identify users. Unfortunately, as a result of this, building a web UI is hard, as the browser needs to perform a privkey decryption step.

IaC

It turns out IaC is hard... My previous attempt, called Provisioner (check out its info in the unfinished section), ended up abandoned when I started to realize the bad choice in attempting to use HCL2 language as the backing for configuration.

This, very very not working and hardly in progress attempt was an attempt at making actual Infrastructure as Code, similar to what Chef had, and while I made some decent progress here, ultimately probably will not continue on this path. Im not a fan of yaml being used for pragmatic things, or any such language for that matter, and find that its more often than not the cause of hacky things people do. This was the main motivator for attempting an actual As Code approach.

View Project

ZFS on Root on Debian (bullseye and up) (Click to Expand)

This was a short project, lasting only a day or two. The scripts provide a way of automatically installing ZFS on Debian, with no human intervention. This primarily rose as I was trying to get a hosting provider to install ZFS on Debian, but they were not sure how. As a result, I wrote these scripts.

These scripts work on VM or Bare Metal. All you need to know are the wwn-* ID's of the disks you want to use for the root pool.

These scripts also provide a recovery script, so that you can quickly jump into a chroot of a ZFS on root.

View Project

Openresty HTAuth via LUA + MySQL (Click to Expand)

While testing a web app that provided no other auth method other than htauth, I begain experimenting with some LUA script. What resulted was this project, which provides an htauth database via MySQL/MariaDB database. The database configuration and query are provided via NGINX/Openresty configuration variables, and the passwords in the database match standard SHA512-CRYPT passwords, ensuring that the database can be an existing database, assuming one also used SHA512-CRYPT passwords.

There was minimal security implemented for this, as it was an experiment, and things like query escaping and shell execution prevention (as this used openssl via resty.shell) were not implemented. If htauth was still widely used and I had further use for this, I might implement more strict things, but until this process ends up a need for me, it will stay as such.

View Project

Logitech X52 HOTAS Spring Mod (Click to Expand)

Pictures

At the recommendation of a few people, I purchased a Logitech X52 HOTAS/Joystick Combo as a recommended starter setup. After a few hours of use, I found myself having problems with fine control of the joystick, because there was almost no resistance to it. Worse, if you tip it on its side, the centering spring couldnt even hold the joysticks weight. So, it sat, collecting dust for many months while I regretted my purchase. I got to talking with a coworker, and he suggested some potential mods that could be done. After a bit of googling, I discovered that this was a fairly common problem, and everyone on the internet have been resolving it with either a 3d printed shim, or something from household items like the top of a CD stack case.

Watching some youtube videos, I saw that these worked, but essentially resulted in less range of motion, and thats just not acceptable to me. A reddit post complained 'why couldnt logitech sell replacement springs', and I realized... why not just replace the spring?! With that in mind, I decided to see if it possible to do.

With the exception of the 'wasted' cost on the springs Im not going to use, I feel that I've turned a $115 HOTAS combo into a $200 one, for $5.

WARNING

This is probably a warranty voiding event, so... yeah, dont complain to me if you break your joystick. Think, and dont use brute force.

Do not twist the joystick around once its removed from the shaft, you can break the wires. the wires are durable, but they wouldnt survive a good yank.

Stock Spring Stats

These were taken using a Harbor Freight caliper, and its definitely not very accurate, but these specs gave me enough to work with

  • Inner Diameter (ID): 25MM (0.984")
  • Outer Diameter (OD): 29MM (1.14")
  • Free Height: 32MM (1.25")
  • Solid Height: 12.75MM (0.5")
  • Spring Rate: ~4.34lb/in

Spring Rate calculated by placing 40oz of weight on the spring and measuring its compression.

Spring Selection

I did some searching for some spring manufacturers, and found a semi-local one that sold in low quantities (https://www.mwcomponents.com/) was where I ultimately ended up purchasing from. Thankfully the X52's spring area is pretty open, which allows for some variation in the Inner/Outer and Free Height. If you are a bigger person, or have a fair bit of muscle, a spring heavier than 20lb/in may work for you, however I did not test any and do not currently have any plans to do so. Some of these parameters can be tweaked to get more variety, but things like too much free height will put a lot of stress on the joystick, or too high of a Solid Length will make it bottom out before you get full range of motion.

I used the following search parameters:

  • Outside Diameter: 1.03" - 1.25" See note below
  • Free Length: 1.25" - 1.46"
  • Inside Diameter: 0.90" - 1.06"
  • Spring Rate: 4.00lb/in - 20lb/in See note 2 below
  • Solid Length: 0.40" - 0.70"

With this search, a few springs were available to me, and I purchased 7 different springs to test. Part numbers are listed below. The largest difference of course, is the spring rate. Once they arrived, I began swapping them, reassembling part of it, testing the feel, and then noting my feelings on it

I have currently settled on the 20lb/in spring, but I may go back to the 17lb/in after a bit of use.

Part Number Cost Spring Rate Thoughts
MW Components - 12271 $5.46 4.2lb/in Way too light, felt equal stock spring
MW Components - 3338 $4.53 5.4lb/in Better than stock, but still really light
MW Components - 11850 $5.58 12lb/in Nice, almost great
MW Components - 12631 $4.28 16lb/in Nice, maybe a bit light still
MW Components - 12540 $3.31 17lb/in Not terrible, maybe a bit stiff
MW Components - 11259 $5.11 19lb/in See Note 1; Too large, did not use
MW Components - 4120 $5.02 20lb/in A bit heavy, but allowed for better fine movement

Note 1: 12540 and 11259 claim to have the same OD, however 11259 did not fit the upper spring cup; 12540 did. Both of these springs OD are 1.118", if you expand your search any, keep the OD max to no more than this, and keep in mind that it may be hit and miss with springs at or larger than this OD

Note 2: High spring rates can cause slight binding against the plastic ring and the lower spring cup, anything above 15lb/in and you should purchase some silicone grease to ease the binding

Required Tools

  • 1 Small (laptop size) phillips screwdriver
  • 1 2.5MM Hex wrench
  • 1 1.5MM Hex Wrench (other items may be used, but this worked perfectly); Needed to push/align the small pin that connects the joystick pieces together.
Optional Things
  • String or light gauge wire and somewhere above the joystick to tie off the joystick handle; Makes working on some steps easier and keeps the wires from being abused
  • Electrical or duct tape, 1" long, 1/4" to 1/8" wide (Optional, but strongly recommended)
  • Silicone Grease (Recommended when using any spring over 12lb/in)

Disassembly

See pictures for more pointers.

  1. Start by removing the handguard screws
  2. There are 2x2.5MM Hex Fine Thread Screws on the top
  3. There are 2x2.5MM Hex Coarse Thread Screws on the bottom
  4. Unscrew the slide thumb screw for the pinky trigger, and set it about midway through the slot, tighten it down.
  5. Using your thumbs while holding the base, push up on the base of the pinky trigger near the thumb screw until it pops off the handguard
  6. Gently Pry the arms of handguard on the bottom away until you can slide it off.
  7. Work the pinky trigger and plate off of the joystick, be careful not to break the wire on the pinky trigger
  8. Unscrew the 4 Phillips screws on the right side of the joystick.
  9. There are 2 screws at the bottom near the spring
  10. There is 1 screw in the center
  11. There is 1 screw near the top
  12. Gently pry the cover on the right side of the joystick off. Start near the spring.
  13. There is a plastic and rubber cover for the pinky spring that is pretty tighten
  14. The top portion is also very tight, be gentle with it

Congrats, you're now inside the joystick. Everything below here is to be done in reverse for testing each spring

  1. Remove the 2 phillips screws inside the joystick that attach the gyro and shaft to the joystick handle.
  2. Gently pull on the plastic below the Z rotation gyro it will slide off the plastic shaft.
  3. Make sure the rotation switch is pushed inward before continuing.
  4. Gently pull the left side of the joystick off the center shaft. Make note of how the pieces go together.
    • Pin on the joystick handle slides into a slot above the rotation switch.
    • Rotation Switch has its own cutout area.
    • Pull the rotation switch button outward during reassembly, it makes it easier. Make sure to push it back in once you reattach the handle to the gryo and shaft.
    • Rotation Switch should be oriented so that the stem of plastic is facing the palm side of the stick (closest to the rotation switch button)
    • Spring goes into a cup area at the bottom.
  5. Slide the actual rotation switch up onto the wires to expose the pin that holds the plastic shaft to the metal shaft
  6. Use a 1.5MM hex wrench to push the pin out. Make sure it does not fall under the lower spring cup.
  7. Pull the plastic shaft upward, and slide it back into the rotation switch.
  8. Push the rotation switch and plastic shaft as far up the wires as you can, make sure you dont get the handle pin stuck in there or it will be difficult, or break things
  9. Using some electrical or duct tape wrap at least 1/4" of the wires, this will prevent chaffing the wires while removing/installing the spring
  10. Much like a key on a keyring, thread the taped wires into the end of the spring, and then thread it the rest of the way off.

Testing

Testing can be done by reassembling the joystick (Step 8-17 in reverse), making sure your joystick is firmly mounted/held in place, and then moving the joystick around. Try making fine movements (EX: move it only a mm or two) as well as slowly going the full range in all directions.

Reassembly tips

  • If using a > 12lb/in spring, before putting the spring on, use the silicone grease and place a small bead along the entire rim of the base where the lower spring cup rides along the base. A little bit goes a long way. Make sure to wipe any excess off after full reassembly and a few full rotations of the joystick to fully lubricate the lower spring cup.
  • Take a 1/4" strip of tape and wrap the wires near the metal shaft, try to only let the springs rub along here so it doesnt chafe the wires.
  • When replacing the pin to rejoin the two center shafts, Use the 1.5MM hex to sort of fish a hole through the wires in the shaft. Keep the pin as straight as possible and against the hex as you slide it in
  • The pin can very easily go in at a slight angle. Dont force it, dont hit it. It needs to go straight and level, without pinching wires. This is literally the most tedious and painful part of the process, so if you get frustrated, take a break.
  • Some of the larger diameter springs are a tight fit in the lower spring cup, you can poke the end of the spring with a small flathead to seat it
  • Make sure you dont pinch any wires, and pay attention to where the wires are in relation to the pin thats on the joystick handle, it can get tangled easily.
  • Once you're starting full reassembly, push the spring down a little bit as you slide the right side cover on.
  • During full reassembly, make sure the plastic/rubber cover for the pinky trigger wire go into the slot correctly, on both sides.
  • Put the hand guard and pinky trigger platform back on at the same time, once the handguard is secured, you can re-secure the pinky platform to the handguard by tightening the screw and then sliding the pinky platform back down with a bit of force.
  • Pay attention to the location of the 2 pairs of hex screws. The fine thread ones go to handguard on the top by the thumb buttons, the coarse thread go at the bottom of the handguard
  • To save time, dont reassemble fully until you're sure you are ready to test for an extended period.
  • Make sure that the finger trigger is properly seated before you put the right side cover back on.

Unfinished / Not-viewable

These are projects that I have not completed, or, are not viewable because im scurred

These are also probably abandoned, maybe, probably

Automation Tools (Click to Expand)

This is an active project. It is not in 'complete' projects, because its 'secret sauce'.

This project is a build and release system for all of my projects on git. This system is extensible to provide building of any language, and provides unified targets that make extending it easy. This system uses make and git (via gitlab), to provide an external automation repository that does not have to be kept in check via git submodules. The system is git tagged using semantic versioning, so that older projects can maintain backward compatibility and reproducibility with minimal effort. It additionally provides an installation method to bring the automation to any repository. As it stands today, the build system can build, lint and deploy Python and Docker images, and can additionally lint shell scripts.

Installation provides a few key files to the target repository, such as a Makefile, project.mk, .gitlab-ci.yml, .gitlab-ci.include.yml, as well as any files specified by the installation (linting rules, additional files, etc). The Makefile is simply a bootstrap that causes the build system to be pulled and/or run. The project.mk provides a project-specific configuration, allowing for zero modification to the automation system, which prevents build system drift.

MFD Display (Click to Expand)

This was a project that I... might have gotten carried away with.

It started when I bought X4:Foundations, a massive spae universe game with flying and fighting, trade, exploration, mining, you name it. Anyway, soon after buying this game, I ended up purchasing a HOTAS (a mod of the hotas is also here among my projects). I spent a lot of time in game getting somewhat frustrated at not having some additional information on a separate screen. I started searching for flight sim screens, and found a very slick looking one, purchasing it, without thinking about the capability of games to put things on that screen. One I discovered this flaw in my plan, I began this project. The plan was to provide a display with game-specific information on it, rendered outside of the game, with stats pulle from the game in realtime, as well as being able to capture button input on the HOTAS and the display that I purchased, in order to manipulate both the game, and the MFD program that I built.

This project was written in python and used pygame to provide the display. The program provided a way to extend for other games with relative ease, and provided a way to use game assets, custom controllers and display button configurations, and more. I completed much of this process, with the intent of working this into other games, such as MechWarrior 5. The original intent was to use IPC, and as long as I had some flexibility in the modding side of the game, could easily facilitate communication. Unfortunately, I became disheartened when I discovered that MW5 did not provide any worthwhile interface that I could communicate with, and ultimately dropped the project. While X4 did have a mod that provided an IPC pipe, a lack of support from the modder made it difficult for me to understand what was going on in order to build up my mod. On top of that, given my current home setup, getting the HOTAS setup / broken down was a very large hassle, and, basically turned my seat into a cockpit (by that I mean, I had to crawl out by standing on my seat to get out).

A video of the functionality being shown for X4 exists, showing off the overview map, fighter map, docking display, and system stats (data generated for testing, not from the game).

Space Engineers Modding (Click to Expand)

Oh SpaceEngineers... I have more hours in this game than I care to admit. Before I stopped playing, I created many mods for SE, ranging from simple things basic QoL improvements, to larger items like a mod called 'Hazard Mechanics' which added a whole new aspect to the game, where things that generated heat/cold/radiation could be hazardous to your health.

Ultimately, I left SE because I did not like the path the Dev studio was taking, where every update came with a new DLC that crippled the game somewhere if you didnt have it, and you wouldnt know it until you had it and realized you were being crippled. Sure, one or two DLC is fine, but now approaching 14 DLC packs, totaling almost an additional $80... is absurd. Combine that with the studio constantly breaking the modding experience, just became more tedious, and I spent more time trying to mod than playing the game.

Some of my favorite mods that I created Ive listed below

  • Hazard Mechanics

    A gameplay aspect mod that added hazards to your ship. Hot and Cold zones, radioactive spaces, all made the way you build your ship more critical. A major portion of this included having to keep your reactors filled with coolant and connected to coolant lines, in order to prevent a runaway and eventual explosion. The custom models were created by another modder whom I paid a few dollars to create.

  • Tool Mechanics

    A gameplay aspect mod that made your tools consume resources, such as drillbits, gasses for welding, and grinding wheels for the grinder. This made it more critical to gather resources to create these consumables, ensuring you couldnt just build or destroy a whole ship without thinking about it.

  • Realistic Solar System

    A Map / System mod that placed modded Sol-like planets in places that lined up with the current orbit of our solar system at the time I made the mod. This involved using a 3d graphing viewer, as well as some real planetary data to create a usable system. It was so realistic, that pluto, at its current orbit, was nearly 1 lightyear from the earth (in the game). This was a fun challenge as it gave a good feel for what it would be like to really actually travel through our system.

  • Small(er) GasTanks

    A block mod that created new tanks that were more compact / differently styled. These models were created by me in blender.

View Project

SynChron (Click to Expand)

This was a project targeted at providing a replacement to systemd-timer and crond, as a centralized scheduler for systems that needed to run scheduled jobs. A server service would listen for Agents and Jobs, and then distribute jobs to agents, as they matched their criteria. Agents would return their job state once the scheduled time ran, for stats tracking

Ultimately this project was abandoned because I got bored, and I did not like the path I was going down with ZeroRPC. This would have been an interesting project to continue on, however, there are not many things that I need which have scheduled jobs

The Provisioner (Click to Expand)

This project was a first (and second) attempt at creating an IaC alternative to things like Terraform, Ansible, Chef, etc. Many of my choices were framed by my job at the time, which was focusing heavily on cloud things. My major complaint with TF is the lack of reusability, for example, if you create an instance on GCP, you have to re-write your entire process for an AWS instance, because none of the parameters match up, and neither do any of the flags/tags, etc. To this end, I aimed to make something that could allow for provisioning on any number of cloud providers, while only having to modify the instance details, such as sizes, disk type, and network info.

IaC is hard, and was made harder by my (bad) choice of selecting HCL2 to try to stay in line with things like Terraform. HCL language is a ridiculous format under the hood, and I cant understand what led someone to think such a design was great. "Its just turtles arrays all the way down".

Ultimately I abandoned this project, although I did have it somewhat functional and capable of doing some things, my design choices put me in a corner because I didnt think ahead.