ggm2

Building Go App with Gitlab Runner on Azure |Part 2

Adefemi Afuwpe
10 min readJan 23, 2021

--

From the last post, we touched a few tasks such as:

  1. Setting up an Azure VM
  2. Opening a port on Azure using NSG (Network Security Group)
  3. Installing Docker and Golang

And for this post, we will be rounding it all up with

  1. Building a static Golang web server
  2. Setting up and Installing GitLab runner
  3. Creating a pipeline on GitLab with the webserver created in point 1

Building a static Golang Web Server

I briefly touched what Golang was in Part 1 of this series, and we also have Golang installed, we created a path on our server for our Go projects at $HOME/Projects. On the server terminal type in cd~ to navigate to the root directory and when you type in ls -a, you should see the Projects directory created. Now we need to change directory to the Projects directory by typing cd Projects you should be in the directory, to confirm this you can type in pwd which means Print Working Directory and you should have an output that shows the path of the current directory you are in.

For every Golang project, it requires a .go file that has the main package and the func main() which serve as an entry file for execution. This post I will be calling my file main.go which will be created in the Projects directory.

To create a new file in Linux, you can use the touch command or use an inbuilt text editor (Vim or nano) along with the name of the file, you can use the command below to create your file:

creating the main.go file

After creating your file, we will be writing some code for the static web server, copy and paste the code below into your text editor:

main.go file

I will explain what the code means by line;

package_main
package_main

Line 1: package main allows us to develop an executable program by telling the Go compiler that the package should compile as an executable rather than a shared library.

package_import

Line 3–11: We are importing packages that we will be using in this application, you should also note that all this package are Go standard library that is they come out of the box when you install Golang.

encoding/json: implements encoding and decoding of JSON
flag: implements command-line flag parsing
fmt: implements formatted I/O with functions analogous to C’s printf and scanf
log: implements a simple logging package. It defines a type, Logger, with methods for formatting output.
net/http: http provides HTTP client and server implementations
os: provides a platform-independent interface to operating system functionality.
time: provides functionality for measuring and displaying the time.

greeting_struct

Line 13–16: Creating Greeting struct. A Struct in Golang is typed collections of field useful for grouping data together to form records.

messageSlice

Line 18–21: Creating a messageSlice. Slice in Golang is a key data type that gives a more powerful interface to sequences than an array. Simply put an array that can be dynamically sized.

messageHandler

Line 23–27: Created a messageHandler. Using the encoding/json package I used the NewEncoder method which returns a new encoder that writes to w which is an http.ResponseWriter and its stored in variable enc, also I used the SetIndent method which instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent. And lastly, I use the Encode method which writes the JSON encoding of messageSlice to the stream, followed by a newline character.

main_func

Line 29–40: This contains the main function which is the entry point for executable programs. Also, note that the main function does not take or return any argument.

host_flag

Line 30–31: Created a host variable that uses the String method in Flag to display a specified name, default value and usage string. The parse method parses the command-line flags and must be called after all flags are defined and before flags are accessed by the program.

srv_var

Line 32: Created an srv variable that stores incoming HTTP connections on the listener with the aid of http.serve from the net/http package.

go_func

Line 33–39: Created a goroutine that exits the code after a certain and then exits gracefully. A goroutine is a lightweight thread of execution, this goroutine is called Anonymous Goroutine. At line 34 am sending a value using Channels in Golang using the <- syntax and what am sending is time.After using the After method from the time package which sends the current time on the returned channel after it has waited for the duration passed in to elapse. For the duration, I used Seconds method from time package as well which returns the number of seconds in floating-point and I multiplied it by 9 to wait for about 9 seconds. Then I used the Println method from fmt package to print a message to the terminal and then used the Close method from http.Server to close all active net.Listeners and any connections in state and lastly I used the Exit method from os and passed in the 0 status code to exit gracefully without no errors, if you pass in a no-zero then the program will terminate with an error.

handleFunc

Line 41: I used the HandleFunc method from net/http package to register the handler function and I then passed in an endpoint (“/message”).

fmt_log

Line 43–44: I used the log and fmt package to print some messages to the terminal using Println method.

listenAndServe

Line 46–48: This is a best practice in Golang for writing if/else in one line. Am catching the errors and also if no error is listening to the port defined in the host variable using the http.ListenAndServer method from net/http pacages. And then if there are any error am using Fatal method from log package to print out this error and then followed by os.Exit(1)

With the above we should have our static web server file created, the next step is to run this code, in your terminal run the commands below:

fmt_and_run_file

You should have the output below in your terminal

go_fmt_&_run

Remember the limit we placed on the webserver was 9 seconds so you need to open up your browser and visit http:// <public_ip_address>:<port_number>/<endpoint> mine is running on http://52.158.224.157:7000/message and you can see the output below, to know your Public IP Address, click on the VM you created and select Overview, you should see the Public IP Address on the right-hand side in your browser. If you by a chance exit from your terminal or got logged out you will need to run the export command like in the image above.

server_output

With this, you have a static Golang web server running on Azure.

baby_wink

Setting Up and Installing GitLab Runner

Like stated in point 3 from part 1, to set up GitLab runner we need to have an executor installed and we have installed Docker🐋. To install GitLab runner locally, the first step is to download the deb/rpm package depending on the OS you are running on your server since we are running Ubuntu, we will be going with deb package.

Before installing the deb package you need to know your server architecture since we are running Ubuntu server we can see our architecture by running the following command

print_architecture

After the OS architecture has been known, the next step is to download the package, you can use the command below for this and the list of the package can be found here.

download_package

The next step is to install the package downloaded, you can use the dpkg command to install this on Debian or Ubuntu image.

install_gitlab

If you got an error try running the command with sudo like the image below:

sudo_install_gitlab

With the package installed, its time to register a runner locally on your server, and to do this run:

register_gitlab_runnner

Registering the runner will require some details from you like

  1. GitLab instance URL (example https://gitlab.com)
  2. Enter the token you obtained to register the runner.
  3. Enter a description for the runner. You can change this value later in GitLab’s user interface.
  4. Enter the tags associated with the runner, separated by commas. You can change this value later in GitLab’s user interface.
  5. Provide the runner executor. For most use cases, enter docker.
  6. If you entered docker as your executor, you’ll be asked for the default image to be used for projects that do not define one in .gitlab-ci.yml.

the image below shows what is required and what should be entered but this might defer depending on how you want to register your runner:

gitlab_runner_registration

To get your runner token, you need to create a GitLab account and then create a new project, at the left side of the screen, scroll down and click on settings > CI/CD > Runners and click on expand, you will be able to find your runner token there, the image below shows these steps:

runner_token

With this few steps, you should have your runner registered and installed and time for the last step.

Creating a pipeline on GitLab with the webserver

With the project created on GitLab, its time we push our webserver code to GitLab and also add .gitlab-ci.yml file at the root of our folder. Create a .gitlab-ci.yml file inside the directory (Projects) where we have our webserver file. paste the following code to the .gitlab-ci.yml which will also include an explanation for each line:

.gitlab-ci.yml

With this, the next step is to push to the project we created on GitLab, and for this, you need to initialize git in your directory, add your remote URL, ad the files, commit the files and push…. Do you hit an error? Just like the image below I also had the same error:

access_error

What this means is that you need to establish access between GitLab and your server to be able to push to GitLab and to do this because GitLab supports secure communication between Git and its servers using SSH keys, I created an SSH Key and I use RSA keys for creating the SSH key, with the image below you will see how I created the SSH key:

create_rsa_ssh_key

After creating the key, in your command line run cat ~/.ssh/id_rsa.pub and this should output your SSH Key, copy the key and go back to GitLab page and click on your avatar in the right-hand corner and select Settings, scroll down till you find SSH Keys then paste the key you copied into the text box and click on Add Key.

Go back to the terminal and run the push command again using git push -u origin master then you should have an output like the one below:

succesfully_pushed

With this, you should see your file in the repository as well as your pipeline file and if you look closely you will see a process icon representing the pipeline in progress just like the image below

process_file_upload

Click on this process and it should navigate you to the image below to show you the pipeline that’s currently running

pipeline_build

And if you click on Jobs just below Pipelines you will see your Job Status just like the image below:

job_output

This brings us to the conclusion of this series and with this, you should have all the jobs with a passed status and also an artifact you can download on the server-build job. That was simple right?

A recap on what was covered

  1. We built a static web server using Golang
  2. We set up and install GitLab runner and also created a project on GitLab
  3. And lastly, we created a pipeline to run our code.

Thanks for reading the post, drop any comments if you have any. ciao😌😎🤗

--

--