Sometimes you just need to redeploy a lot of resources for testing because you’re building something for a customer. For me these scenario’s always go into scripting or templates. That means for every change I want to be redeploy the environment and see if everything is still working. For that I need random names. You could pick a name, add a number and up the number for every new deployment but, where’s the fun in that?

Yesterday I spent my lunch break stitching together a PowerShell script to generate a name based on Marvel characters that I could then use to base the name of my resources on. It’s not the cleanest script.. but it works!

Requirements

You could do this in any language you want. I might consider turning this into an Azure Function but for now it does the job 🙂

Code here: https://github.com/whaakman/powershell-random-marvel-names

The solution

Querying the Marvel API is pretty straight forward, but the documentation is lacking proper examples. First we need to authenticate to the Marvel API (gateway.marvel.com). For this we need a private key, a public key, timestamp and a hash (MD5).

The keys can be retrieved from visiting the Marvel Developer Portal. We’ll put these as variables in the script. Additionally we’ll create a timestamp using Get-Date.

The MD5 hash needs to be generated and must contain both keys and the timestamp.

# Public and Private Keys. You can get these from https://developer.marvel.com/
$publicKey = "<PRIVATE KEY>"
$privateKey = "<PUBLIC KEY>"
# API Call requires a time stamp
$ts = Get-Date -Format s

# The required hash can be generated from stitching together the time stamp, public key and private key
# After stitching them together, generate the required MD5 hash
$string = $ts+$privateKey+$publicKey
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($string)))
$hash = $hash.ToLower() -replace '-', ''

Now that we have the basics set up we can start doing some requests.

Performing the query requires you to add the public key, hash and timestamp as parameters for authentication.

Unfortunately the Marvel API doesn’t have some kind of feature that allows you to request a random name. It also limits the results to 100 super heroes. As there are about 1400, we need to overcome that limit.

We can do this by doing performing an initial query and store the total number of results in a variable ($totalNames).

# First we do an initial call, the API only returns 100 results, we can change the result set by using an offset
# To know the range for the offset we need to know how much characters the API contains
$charactersURINoOffset = "http://gateway.marvel.com/v1/public/characters?apikey=$publicKey&hash=$hash&ts=$ts&limit=1"

$Params = @{
    ContentType = 'application/json'
    Method = 'Get'
    URI = $charactersURINoOffset
}

$resultNoOffset = Invoke-RestMethod @Params
$totalNames = $resultNoOffset.data.total

Now that we have to total names we can randomize our results in a next call by having a random offset (Get-Random -Minimum 1 -Maximum $totalNames) and store the actual random names in $resultOffset.

# Now we know the total number of results and we can randomize the offset
$offset = Get-Random -Minimum 1 -Maximum $totalNames
$charactersURIOffset = "http://gateway.marvel.com/v1/public/characters?apikey=$publicKey&hash=$hash&ts=$ts&limit=100&offset=$offset"

$Params = @{
    ContentType = 'application/json'
    Method = 'Get'
    URI = $charactersURIOffset
}

# Let's make the actual call
$resultOffset = Invoke-RestMethod @Params

The $resultOffset now contains a list of names, we only want a single name so $names |Get-Random will resolve that.

Now we’re ready to manipulate some strings to make sure we follow the naming conventions of Azure. This is pretty challenging as it can differ per Resource Type so if you’re going to use this, you might need to add some stuff.

Basically what we’re doing is stripping all the special characters, convert everything to lower case and remove everything after the parentheses.

Finally, for uniqueness we’re appending a random 4 digit number.

# Store the list of names in $names and then remove characters that aren't support by Azure naming conventions
# Quote out the stuff you don't need.
# Create a list of special chars for replace
$chars = '!', '""', ' ', '#', '£', '$', '%', '&', '^', '*', '(', ')', '@', '=', '+', '<', '>', '.', '?', '/', ':', ';', "'", "-"
$chars = [string]::join('|', ($chars | % {[regex]::escape($_)}))

$names = $resultOffset.data.results.name
$name = $names | Get-Random
$name = $name.split('(')[0] 
$name = $name.ToLower()
$name = $name -replace $chars, ""

# Add a random number for uniqueness
$randomNumber = Get-Random -Minimum 1000 -Maximum 9999
$result = $name + $randomNumber

# Return the result
Write-host $result

And that’s it! Pretty straight forward, could use some improvements but works for now 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.