DEV Community

Cover image for Learning Go - Delivering my first contribution to AzBrowse
Ben Greenier
Ben Greenier

Posted on

Learning Go - Delivering my first contribution to AzBrowse

Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to create software to help solve really tricky problems, and share our stories as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.

What is AzBrowse

AzBrowse is an interactive CLI for interacting with Azure resources - inspired by https://resources.azure.com. It was created by a few of my colleagues here at Microsoft to allow for faster Azure resource management directly from the shell. Written entirely in Go and maintained by folks down the hall, AzBrowse seemed like the best candidate for me to learn a new language and start contributing quickly.

GitHub logo lawrencegripper / azbrowse

An interactive CLI for browsing Azure, inspired by http://resources.azure.com/

AzBrowse

An interactive CLI for browsing azure resources, inspired by resources.azure.com

Go Report Card Go Doc Release release

Status

This is a pet project which has matured thanks to support from awesome contributions.

asciicast

Warning: Please familiarize yourself with the code and the how-to's before using it in a production environment.

Cool what else can it do?

Lots check out the guided tour here.

  • Edit/Update resource
  • Multi-resource delete
  • Actions on resources such as restart and list-keys
  • ASCII Graphs for resource metrics
  • Interactive command panel for filtering and more
  • Build custom views from Azure Resource Graph Queries

For advanced config review the settings page here. For command line arguments and docs see this page.

Contributing

Take a look at the guide here for a guide on the design of azbrowse and then a look here for how to get started on deving

Install/Run

Pre-req: Ensure you have the az command from Azure CLI setup on your…

Learning Go

I decided I needed to learn Go given it's increasing prominence in backend stacks like Kubernetes. As I begin to need to work with folks using these technologies, being able to understand and even modify these Go implementations will be super helpful. To begin, I read the entirety of the Effective Go documentation. That was a great start, and genuinely a well written resource. However for more practical stuff, I found myself using Go by Example quite a bit - My colleague recommended it and it doesn't disappoint. Go By Example includes little snippets of code for solving common Go problems - so not only do you get a brief description of a topic, but a fully runnable code example as well.

My first actual Go task was to add some additional regex parsing logic, and increase the test coverage of that logic. It was actually just an open issue on AzBrowse that one of the core maintainers directed me to. It ended up being a pretty great place to start, given that I had an understanding of regex already, so the only new thing was Go.

Regex in Go

AzBrowse was already using regexp for regex parsing, which as I understand it is the "Way to do it" in Go. I actually found the package documentation to be a little convoluted - I was surprised that the docs referenced other sections of the same doc for seemingly simple concepts. For example, FindAllStringSubmatch references a definition of All that isn't linked nor inline. This added a tiny bit of extra friction to the development process that I wasn't expecting. That said, the library itself seems pretty feature rich - Regex101 even has support for it's regex pattern format. This made it easy to test the regex as I was working with it.

Regex101 Example

Testing in Go

AzBrowse uses testify for authoring and running tests. This was pretty easy to get up to speed on - In fact, I didn't even need to read the docs. A few existing examples and previous experience with other test frameworks was sufficient. This made authoring and modifying tests even faster.

One challenge I did face was invalid assertion messages. When I broke the existing tests, the assertion failure messages were all the same. It was obvious to me that the assertions (all on different values) were not all failing for the same reason. Can you find the issue in the code below?

// testCases is an array of objects, where each object contains fields:
// desc, input, output
// describing the test, providing the input, and the expected output
for _, test := range testCases {
    t.Run(test.desc, func(t *testing.T) {
        t.Parallel()
        output := stripSecretVals(test.input)
        assert.Equal(t, output, test.expected)
    })
}
Enter fullscreen mode Exit fullscreen mode

If you can, that's awesome! If not don't worry, neither could I. The answer is lies in how go closure scopes work. As I understand it, this occurs because our actual test run occurs inside a closure, and at some point in the future. Because of that, the variable test is bound to the last value in the actual slice (testCases) for all assertions.

To fix this, and make the assertion failures correct, I used shadowing - to ensure that the value of test would be correctly bound to the right value in each iteration of the loop.

// testCases is an array of objects, where each object contains fields:
// desc, input, output
// describing the test, providing the input, and the expected output
for _, test := range testCases {
    // shadow test value to ensure assertion failures
    // print the correct test.expected value
    test := test

    t.Run(test.desc, func(t *testing.T) {
        t.Parallel()
        output := stripSecretVals(test.input)
        assert.Equal(t, output, test.expected)
    })
}
Enter fullscreen mode Exit fullscreen mode

After making that change, my assertions correctly displayed the right errors! That made it pretty easy to add more entries to testCases to add more data-driven tests to the project.

New features

With my newly learned Go skills applied, I was able to open a PR that added more masking of secret values to the --demo mode of AzBrowse. This mode is super useful for demos or videos, where you want to prevent displaying these sensitive values. I tried it out with my Azure subscription, and got to see everything working! The new masking is added from v1.2.531 and up.

In Conclusion

Learning the basics of Go was pretty straightforward, thanks to the great documentation put together by the Go team, and some external resources on the web. I was able to transition from learning Go to contributing in under 3 days!

Thanks for reading. If you've had a chance to learn and use Go, let me know what you thought about the process in the comments below. If you'd like to support me personally, follow me on twitch and/or twitter.

💙🌈
-Ben

Resources

Top comments (0)