• DDD Adelaide is back for 2023

    Back in 2019, Andrew and I ran the first ‘rebooted’ DDD Adelaide conference. The response from the Adelaide developer community was amazing, and we were all set to run again in 2020. For some reason, we had to put plans on hold for a few years, but I’m excited to announce that we are back for 2023!

    DDD Adelaide 2023 logo

    It’s awesome to have Claire Webber, Harnoor Bandesh, Isaac Mann and Will Turner join the organising team. Check out Isaac’s post about why he got involved.

    Tickets are on sale now, but numbers are limited, so get in quick!

    If you are interested in speaking, we are now accepting talk proposals. We are looking for a diverse range of speakers and topics. You don’t need to be an expert speaker, we are happy to help you prepare your talk.

    Finally, an event like this doesn’t happen without sponsors. We strive to keep the ticket price low so that it won’t be a barrier for anyone to attend. But there are a surprising number of expenses involved in running the event, and income from tickets doesn’t come close to covering the costs. That’s why we need sponsors, so if you work for a company that would like to support the Adelaide developer community, please get in touch.

    Call to action

    David and Andrew standing in front of a seated crowd at DDD 2019

    Hope to see you there! I’ll be the tall guy wearing the special edition ‘DDD’ Akubra 😊

  • HashiCorp Certified: Terraform Associate (003)

    I’ve been using Terraform quite a bit recently and noticed that HashiCorp have a Terraform Associate certification. Reviewing the exam objectives it sounded like it seemed to cover most of the things I’ve already been doing, so I decided to give it a go.

    Terraform certified associate badge

    The exam is run by PSI, so was a slightly different experience to those I’ve taken for Microsoft certifications. The sign-in process was a bit simpler (eg. scanning your ID with your webcam rather than having to upload them from your phone). The exam software required that I turn off a few background processes (OneDrive, a Zoom background process and the Virtual Machine Management Service). Once I’d done that the software was happy to proceed and when the proctor was satisfied with my room and desk setup I was able to start the exam.

    I finished the exam in good time and I was pleased to learn that I passed!

    The email summary of my results included a breakdown of how I went in each of the areas covered.

    Overall Score: 78%

    Breakdown by content area:

    1. Understand infrastructure as code (IaC) concepts: 100%
    2. Understand the purpose of Terraform (vs other IaC): 100%
    3. Understand Terraform basics: 87%
    4. Use Terraform outside the core workflow: 100%
    5. Interact with Terraform modules: 40%
    6. Use the core Terraform workflow: 88%
    7. Implement and maintain state: 72%
    8. Read, generate, and modify configuration: 63%
    9. Understand Terraform Cloud capabilities: 100%

    So looks like modules are an area I’m not as strong on! That’s fair as I haven’t made a lot of use of them so far.

    If you’re using Terraform, then I’d encourage you to go ahead and take the exam. Have a look at the study guide, sample questions and exam review to ensure you’re comfortable with all the topics being covered and how questions will be asked. Then register for the exam and give it a go!

  • Azure DevOps API PropertiesCollections

    I was looking at some of the Azure DevOps API documentation and noticed that some of the endpoints mention a properties object of type PropertiesCollection. Unfortunately, the details for that data structure are not particularly helpful, and I couldn’t figure out how to use it. Some pages include examples, but none that I could find included an expanded properties object.

    To figure out how to use it, I created a simple .NET console application. I added references to the following NuGet packages:

    • Microsoft.TeamFoundationServer.Client
    • Microsoft.VisualStudio.Services.InteractiveClient
    • Microsoft.VisualStudio.Services.Release.Client
    using Microsoft.VisualStudio.Services.Common;
    using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Clients;
    using Microsoft.VisualStudio.Services.WebApi;
    
    const string collectionUri = "https://dev.azure.com/organisation";
    const string projectName = "MyProject";
    const string pat = "YOUR-PAT-HERE";
    const int releaseId = 20;
    
    var creds = new VssBasicCredential(string.Empty, pat);
    
    // Connect to Azure DevOps Services
    var connection = new VssConnection(new Uri(collectionUri), creds);
    
    using var client = connection.GetClient<ReleaseHttpClient>();
    
    // Get data about a specific release
    var release = await client.GetReleaseAsync(projectName, releaseId);
    
    release.Properties.Add("Thing", "hey");
    
    // Send the updated release back to Azure DevOps Services
    var result = await client.UpdateReleaseAsync(release!, projectName, releaseId);
    
    Console.WriteLine();
    

    This allowed me to create a property key and value, that I could then examine by querying the item (in this case a ‘classic’ release), by calling the GET endpoint. eg.

    https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases/{releaseId}?propertyFilters=Thing&api-version=7.0
    

    Note that you need to specify the propertyFilters parameter. Otherwise the properties` object will not be included in the response.

    And in doing that, we can see the JSON data structure!

        "properties": {
            "Thing": {
                "$type": "System.String",
                "$value": "hey"
            }
        }
    

    So, to add a property, you need to add a new key/value pair to the properties object, where the key is the name of the property, and the value is an object with two properties: $type and $value. The $type property is the type of the value, and the $value property is the value itself.

    The documentation clarifies the types supported:

    Values of type Byte[], Int32, Double, DateType and String preserve their type, other primitives are retuned as a String. Byte[] expected as base64 encoded string.

    (I think ‘DateType’ is a typo, and should be ‘DateTime’)

    Now that we know the shape of the data, I can jump back to PowerShell and use that to add a new property:

    $uri = "https://vsrm.dev.azure.com/$($organisation)/$($project)/_apis/release/releases/$($releaseId)?api-version=7.0&propertyFilters=Extra"
    
    $result = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
    
    if (-not ($result.properties.Extra)) {
        $result.properties | Add-Member -MemberType NoteProperty -Name "Extra" -Value @{
            "`$type" = "System.String"
            "`$value" = "haaaa"
        }
    }
    $body = $result | ConvertTo-Json -Depth 20
    
    "Updating via PUT"
    
    Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -Body $body -ContentType "application/json"