Hello my friend,
We continue our journey in the realm of software development, or how some people call it programming. In the previous blog post we’ve introduced you to variables, which are the storage containers for your data. Today we’ll take a look into functions, which are next essential building of any application.
How Is Automation Important Today?
Interviewing people to various roles at high-profiles companies, I was sadly surprised that there is very low number of people who really understand network and IT infrastructure automation and are capable to write the Python code to do so. And I’m talking about companies, who are genuinely interested in good automation engineers. Don’t waste your chance, start learning network automation today:
We offer the following training programs in network automation for you:
- Zero-to-Hero Network Automation Training
- High-scale automation with Nornir
- Ansible Automation Orchestration with Ansble Tower / AWX
- Expert-level training: Closed-loop Automation and Next-generation Monitoring
During these trainings you will learn the following topics:
- Success and failure strategies to build the automation tools.
- Principles of software developments and the most useful and convenient tools.
- Data encoding (free-text, XML, JSON, YAML, Protobuf).
- Model-driven network automation with YANG, NETCONF, RESTCONF, GNMI.
- Full configuration templating with Jinja2 based on the source of truth (NetBox).
- Best programming languages (Python, Bash) for developing automation
- The most rock-solid and functional tools for configuration management (Ansible) and Python-based automation frameworks (Nornir).
- Network automation infrastructure (Linux, Linux networking, KVM, Docker).
- Orchestration of automation workflows with AWX and its integration with NetBox, GitHub, as well as custom execution environments for better scalability.
- Collection network data via SNMP and streaming telemetry with Prometheus
- Building API gateways with Python leveraging Fast API
- Integration of alerting with Slack and your own APIs
- … and many more
Moreover, we put all mentions technologies in the context of real use cases, which our team has solved and are solving in various projects in the service providers, enterprise and data centre networks and systems across the Europe and USA. That gives you opportunity to ask questions to understand the solutions in-depth and have discussions about your own projects. And on top of that, each technology is provided with online demos and labs to master your skills thoroughly. Such a mixture creates a unique learning environment, which all students value so much. Join us and unleash your potential.
What Are We Going To Talk Today About?
We already used functions in previous two blog posts in this series, but we haven’t dug into its details. Today we are going to cover this gap by answering these two questions:
- How to create your own function in Python and Go (Golang)?
- How to use functions, created by someone before in your code?
Explanation
When I’m teaching live classes, I always provide the following analogy to my students:
Function in programming language is pretty much the same as function in maths: it may have some input parameters, does some computation / actions and produces some result.
For reference, let’s take to a notation of function in maths:
1 y = f(x)
In this example:
- x is an argument passed to function (it could me multiple arguments)
- f(x) is a processing of x and transforming it another value (which possibly may be the same)
- y is a result of function execution
In programming languages, the logic is pretty much the same:
- Functions may have arguments; although, it is not mandatory. There could be functions, which don’t take any arguments, if this is inline with the business logic.
- Functions typically have some code to execute, which is what their business logic is. It could be compute some result, connect to network device and collect some data, do the API call(s), etc.
- Functions typically return some result; although it is not mandatory. It could be that rather than returning some result back to the callee, functions perform so called side effects (e.g., writing to file and storing it to a disk or remote object storage such as AWS S3, GCS, etc).
Depending on the programming language the syntax how the function is defined may vary, but overall meaning stay the same: the function signature signals how the function is named, what arguments it may have and which output it shall have.
You may ask the question: “That’s clear, but why do I need functions at all?” One of the key concept of software development is called DRY, what stands for Don’t Repeat Yourself. If you think you may need to use some processing steps more than once, you may want to put them into a function, which you then call as many time as you need in different parts of your application. Even if you don’t plan to use these processing steps more than once, it is still recommended to create functions to contain some blocks of your business logic, so that it is easier to write and understand the code of your application as you can follow the general business logic leveraging the functions name within the main body and separately to zoom into each block implementation within function.
Following the very same idea of not repeating itself, some useful functions you may create once for one project and re-use in others. What brings us to the topic of external modules. There are lots of useful modules for all programming languages out there, especially for Python (and a bit less, but sill existing, for Go (Golang)). External modules are major driving force for popularity of any programming language, as they allow to build the business applications quicker and in a more reliable way. Quicker because you don’t need to do heavy lifting of low-level processing and use module straight to get the desired result. In a more reliable way because, if you chose external module right, you already get tested and verified functions, working across multiple places worldwide so they are battle-proven and has lots of bugs and corner cases addressed. Using external modules elevates DRY concept to the next level.
Examples
With these in mind, let’s see how you can create your own functions or import external functions in your code in Python and Go / Golang.
The scenario we are going to cover is the following:
In the previous blog post we’ve created variable with username and assigned the value directly in the code (so called “hard-coded”). Obviously, this is not the correct approach as in any IT infrastructure / network (as we speak from IT infrastructure / network automation perspective) you may have different usernames for different systems. That’s not even talking about having passwords in your code, which is one of the biggest and wide-spread security risks. So what we are going today is to write an application, which reads user credentials (username and password) from the environment in Linux and Mac (possible in Windows as well, but I haven’t written on Windows for a while, so I cannot be 100% sure).
Python
In Python there are multiple ways how you can import external modules. Join our zero-to-hero network automation training to get the in-depth view.
Before we provide you code snippet, we do some theoretical part really quick. At a bare minimum, the function in Python looks like that:
1
2
3 def func_name(a, b):
...
return some_value
Where:
- ‘def func_name(a,b):’ is a function signature
- a and b are arguments
- some_value is a result of function execution, what is returned back to callee. Commonly, this is name of variable containing some value
With Python being dynamically typed language this works; however, for anyone reading this snippet it is unclear, what are the data types a and b shall have, as well as what data type shall have some_value.
Therefore, the recommended way to define function is the following:
1
2
3 def func_name(a: str, b: int) -> str:
...
return some_value
In this case you do hints, which suggests which data type you shall pass in and expect back. These hints are actively used by all the development environments, such as VSCode.
Ok, now you have enough information to write function, so here we go with our example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """From Python to Go: Python: 003 - imports and function"""
# Import part
import os
# Functions
def get_username() -> str:
"""Helper function to get username"""
return os.getenv("AUTOMATION_USERNAME", "")
def get_password() -> str:
"""Helper function to get password"""
return os.getenv("AUTOMATION_PASSWORD", "")
# Execution
username = get_username()
password = get_password()
print(f"{username=}, {password=}")
Here what happens:
- Using import keyword you import external module named os. This module contains a lot of useful functions to work with the underlying operating system.
- Then you define (using keyword def) two functions named get_username() and get_password(). Both of them don’t take any input arguments at the moment (we will add them later in the series, when we cover conditionals). We use the recommended way to create function signature so that other developers know what to expect as a result of function execution.
- Within each function we return result using the keyword return. What we return is the result of another function execution called getenv() from os module. The function getenv() takes two arguments, that is name of environmental key as well as the default value, which will be used if the environmental variable isn’t set. In the official documentation for this module you can find what other functions you have available at your disposal.
- Then in the execution part you call your very own functions get_username() and get_password() (pay attention, to call the function, you add parenthesis `()`). As result of their execution, you will have two variables created and values assigned to them.
- Variables are printed using print() function (that’s the function we mentioned in the very beginning, which we use already for a while) using f-string approach covered in the previous blog.
And here is execution:
1
2
3
4
5 $ export AUTOMATION_USERNAME="karneliuk"
$ export AUTOMATION_PASSWORD="lab"
$ python main.py
username='karneliuk', password='lab'
First of all, we’ve created Linux / MAC environmental variables and then executed out code.
There are two more important points you shall be aware of:
- Some modules are distributed together with Python, they are part of so called standard package distribution. You can see all the standard packages in official documentation.
- If module isn’t distributed together with Python by default, you can install it using pip tool. We’ll cover that in later blogs, when we will need non-standard packages.
Let’s move to Go (Golang).
Go (Golang)
Being strict typed language, Go has the only one way to create function signature:
1
2
3
4 func funcName(a string, b int) string {
...
return some_value
}
As you can see, the syntax is very similar to Python with differences that you use key word func instead of def. As well as curly braces to wrap the content of the function.
Without further ado, let’s take a look into Go (Golang) code snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 /*From Python to Go: Go: 003 - imports and function*/
package main
// Import part
import (
"fmt"
"os"
)
// Aux functions
func getUsername() string {
/* Helper function to get username */
return os.Getenv("AUTOMATION_USERNAME")
}
func getPassword() string {
/* Helper function to get password */
return os.Getenv("AUTOMATION_PASSWORD")
}
// Main
func main() {
// get variables
username := getUsername()
password := getPassword()
fmt.Printf("username=%v, password=%v\n", username, password)
}
Some explanations to the Go code:
- You use the very same “import” keyword. You need it only once and then within parenthesis you write all the modules you want to import.
- You create (using keyword func) two your functions getUsername() and getPassword(). They don’t take any arguments and return value with string data type back.
- The return value is coming from the execution of another function Getenv(), from os module, which takes a single argument with the name of the environmental key. Check which other functions are available for you in this module.
- In main body we create variables assigning them result of your custom functions execution and then using formatted string we print it to Stdout utilising function Printf() from fmt module.
In all fairness, for Python os.getenv() we can also provide only one input argument with the name of the environmental key. We recommended you to experiment with that.
Let’s execute this Go (Golang) application:
1
2 $ go run .
username=karneliuk, password=lab
The two points we mentioned in Python, are applicable for Go as well:
- Some modules are coming together with Go as part of std distribution. You can find the packages and their details on Go website.
- If we need external package, which is not part of standard distribution, we need to download it using “go get” command. More on that will be provided in later blogs.
Lessons in GitHub
You can find the final working versions of the files from this blog at out GitHub page.
Conclusion
Functions and variables are essential building blocks of any application. You will find it literally everywhere, in any programming language. The reason why we brought them, before covering other functions now is because just in the next blog post we will need them a lot. Up for now Go / Golang and Python was very similar, but since the next blog post you will start seeing differences. Take care and good bye.
Support us
P.S.
If you have further questions or you need help with your networks, I’m happy to assist you, just send me message. Also don’t forget to share the article on your social media, if you like it.
BR,
Anton Karneliuk