Skip to content

Commit

Permalink
docs: add Go tutorial and reference (#723)
Browse files Browse the repository at this point in the history
* Go tutorial and reference

* Run pipeline

* minor improvements to the go docs

* Add --fail to all curl commands

* tutorial fixes

* Replace second part of the tutorial with a new endpoint

* Add missing space

* update to ubuntu 24.04

* minor corrections

* shorten line

* Fixes and improvements

* Apply suggestions from code review

Co-authored-by: Ben Hoyt <[email protected]>

* Remove unneeded go mod tidy

* Run ci

* Replace you with we and remove Ubuntu version dependency

* go mod init before creating the main.go file

* go-framework and typo

* Run docker as a regular user

* Link to pebble docs in the first occurrence

* quote sudo

* intermediate cleanup -> stop the application

* add next steps part

* typo

* Apply suggestions from code review

Co-authored-by: Tiago Nobrega <[email protected]>

* update link as the other tutorials

* suggestions from code review

* Update docs/reference/extensions/go-framework.rst

Co-authored-by: Rafid Bin Mostofa <[email protected]>

* Suggestion for rewording about the http server create by the go app

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Address comments in code review

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* experimental in the beginning of the tutorial. minor rearrangement

* Add information about the estimated time and skills required acquired

* remove note on amd64 and the bare base

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

* Update docs/tutorial/go.rst

Co-authored-by: Michael DuBelko <[email protected]>

---------

Co-authored-by: Ben Hoyt <[email protected]>
Co-authored-by: Tiago Nobrega <[email protected]>
Co-authored-by: Rafid Bin Mostofa <[email protected]>
Co-authored-by: Michael DuBelko <[email protected]>
  • Loading branch information
5 people authored Nov 27, 2024
1 parent 834271c commit 521c3f7
Show file tree
Hide file tree
Showing 10 changed files with 629 additions and 14 deletions.
71 changes: 71 additions & 0 deletions docs/reference/extensions/go-framework.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.. _go-framework-reference:

go-framework
----------------

The Go extension streamlines the process of building Go application
rocks.

The extension builds and copies the Go binary file to the rock.
By default, the base ``bare`` is used, to generate a lightweight image.


.. note::
The Go extension is compatible with the ``bare`` and ``[email protected]``
bases.

Project requirements
====================

To use the ``go-framework`` extension, there must be a ``go.mod`` file
in the root directory of the project.


``parts`` > ``go-framework/install-app`` > ``organize``
=========================================================

If the main package is in the base directory and the rockcraft name
attribute is equal to the go module name, the name of the binary will
be selected correctly, otherwise you will need to adjust it.

You can use this field to specify a different binary to be used as the
main application, without having to override the service command. For example,
if your Go application contains a ``main`` package in the directory
``cmd/anotherserver``, the name of the binary will be ``anotherserver``
and you can override the main application to use the binary with the
next snippet:

.. code-block:: yaml
parts:
go-framework/install-app:
organize:
bin/anotherserver: usr/local/bin/<rockcraft project name>
``parts`` > ``go-framework/assets`` > ``stage``
=========================================================


Some files, if they exist in the project root, are included by
default in the rock in the ``/app`` directory. These include:
``migrate``, ``migrate.sh``, ``templates/`` and ``static/``.

You can customise the files to include by overriding the ``stage`` property
of the ``go-framework/assets`` part:

.. code-block:: yaml
parts:
go-framework/assets:
stage:
- app/migrate
- app/migrate.sh
- app/static
- app/another_file_or_directory
Useful links
============

- :ref:`build-a-rock-for-a-go-application`
1 change: 1 addition & 0 deletions docs/reference/extensions/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ initiating a new rock.
flask-framework
django-framework
fastapi-framework
go-framework
8 changes: 8 additions & 0 deletions docs/reuse/tutorial/code/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ execute: |
# [docs:install-docker]
sudo snap install docker
# [docs:install-docker-end]
# [docs:docker-regular-user]
sudo addgroup --system docker
sudo adduser $USER docker
newgrp docker
sudo snap disable docker
sudo snap enable docker
# [docs:docker-regular-user-end]
35 changes: 22 additions & 13 deletions docs/reuse/tutorial/setup.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
We recommend starting from a clean Ubuntu 22.04 installation. If you don't have
one available, you can create one using `Multipass`_:
We recommend starting from a clean Ubuntu installation. If we don't have
one available, we can create one using `Multipass`_:

.. tabs::

Expand All @@ -11,9 +11,9 @@ one available, you can create one using `Multipass`_:
snap services multipass
If you see the ``multipass`` service but it isn't "active", then you'll
need to run ``sudo snap start multipass``. On the other hand, if you get
an error saying ``snap "multipass" not found``, then you must install
If we see the ``multipass`` service but it isn't "active", then we'll
need to run ``sudo snap start multipass``. On the other hand, if we get
an error saying ``snap "multipass" not found``, then we must install
`Multipass <install-multipass_>`_:

.. code-block:: bash
Expand All @@ -30,11 +30,11 @@ one available, you can create one using `Multipass`_:
See `Multipass installation instructions <install-multipass_>`_, switch
to macOS in the drop down.

Then you can create the VM with the following command:
Then we can create the VM with the following command:

.. code-block:: text
multipass launch --disk 10G --name rock-dev 22.04
multipass launch --disk 10G --name rock-dev 24.04
Finally, once the VM is up, open a shell into it:

Expand All @@ -52,31 +52,40 @@ and initialised:
sudo snap install lxd
lxd init --auto
In order to create the rock, you'll need to install Rockcraft:
In order to create the rock, we'll need to install Rockcraft:

.. literalinclude:: /reuse/tutorial/code/task.yaml
:language: bash
:start-after: [docs:install-rockcraft]
:end-before: [docs:install-rockcraft-end]
:dedent: 2

We'll use Docker to run the rock. You can install it as a ``snap``:
We'll use Docker to run the rock. We can install it as a ``snap``:

.. literalinclude:: /reuse/tutorial/code/task.yaml
:language: bash
:start-after: [docs:install-docker]
:end-before: [docs:install-docker-end]
:dedent: 2

By default, Docker is only accessible with root privileges (``sudo``). We want
to be able to use Docker commands as a regular user:

.. literalinclude:: /reuse/tutorial/code/task.yaml
:language: bash
:start-after: [docs:docker-regular-user]
:end-before: [docs:docker-regular-user-end]
:dedent: 2

.. warning::
There is a `known connectivity issue with LXD and Docker
<lxd-docker-connectivity-issue_>`_. If you see a
<lxd-docker-connectivity-issue_>`_. If we see a
networking issue such as "*A network related operation failed in a context
of no network access*", make sure you apply one of the fixes suggested
of no network access*", make sure to apply one of the suggested fixes
`here <lxd-docker-connectivity-issue_>`_.

Note that you'll also need a text editor. You can either install one of your
choice or simply use one of the already existing editors in your Ubuntu
Note that we'll also need a text editor. We can either install one of our
choice or simply use one of the already existing editors in the Ubuntu
environment (like ``vi``).

.. _`lxd-docker-connectivity-issue`: https://documentation.ubuntu.com/lxd/en/latest/howto/network_bridge_firewalld/#prevent-connectivity-issues-with-lxd-and-docker
Expand Down
18 changes: 18 additions & 0 deletions docs/tutorial/code/go/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"fmt"
"log"
"net/http"
)

func helloWorldHandler(w http.ResponseWriter, req *http.Request) {
log.Printf("new hello world request")
fmt.Fprintln(w, "Hello, world!")
}

func main() {
log.Printf("starting hello world application")
http.HandleFunc("/", helloWorldHandler)
http.ListenAndServe(":8000", nil)
}
26 changes: 26 additions & 0 deletions docs/tutorial/code/go/main.go.time
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"fmt"
"log"
"net/http"
"time"
)

func helloWorldHandler(w http.ResponseWriter, req *http.Request) {
log.Printf("new hello world request")
fmt.Fprintln(w, "Hello, world!")
}

func timeHandler(w http.ResponseWriter, req *http.Request) {
log.Printf("new time request")
now := time.Now()
fmt.Fprintln(w, now.Format(time.DateTime))
}

func main() {
log.Printf("starting hello world application")
http.HandleFunc("/", helloWorldHandler)
http.HandleFunc("/time", timeHandler)
http.ListenAndServe(":8000", nil)
}
113 changes: 113 additions & 0 deletions docs/tutorial/code/go/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
###########################################
# IMPORTANT
# Comments matter!
# The docs use the wrapping comments as
# markers for including said instructions
# as snippets in the docs.
###########################################
summary: Getting started with Go tutorial

environment:

execute: |
set -x
# [docs:install-go]
sudo snap install go --classic
# [docs:install-go-end]
# [docs:mod-init-go]
go mod init go-hello-world
# [docs:mod-init-go-end]
# [docs:go-build]
go build .
# [docs:go-build-end]
./go-hello-world &
retry -n 5 --wait 2 curl --fail localhost:8000
# [docs:curl-go]
curl --fail localhost:8000
# [docs:curl-go-end]
kill $!
# [docs:create-rockcraft-yaml]
rockcraft init --profile go-framework
# [docs:create-rockcraft-yaml-end]
sed -i "s/name: .*/name: go-hello-world/g" rockcraft.yaml
# [docs:experimental]
export ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true
# [docs:experimental-end]
# [docs:pack]
rockcraft pack
# [docs:pack-end]
# [docs:ls-rock]
ls *.rock -l --block-size=MB
# [docs:ls-rock-end]
# [docs:skopeo-copy]
rockcraft.skopeo --insecure-policy \
copy oci-archive:go-hello-world_0.1_amd64.rock \
docker-daemon:go-hello-world:0.1
# [docs:skopeo-copy-end]
# [docs:docker-images]
docker images go-hello-world:0.1
# [docs:docker-images-end]
# [docs:docker-run]
docker run --rm -d -p 8000:8000 \
--name go-hello-world go-hello-world:0.1
# [docs:docker-run-end]
retry -n 5 --wait 2 curl --fail localhost:8000
# [docs:curl-go-rock]
curl --fail localhost:8000
# [docs:curl-go-rock-end]
[ "$(curl localhost:8000)" = "Hello, world!" ]
# [docs:get-logs]
docker exec go-hello-world pebble logs go
# [docs:get-logs-end]
# [docs:stop-docker]
docker stop go-hello-world
docker rmi go-hello-world:0.1
# [docs:stop-docker-end]
## Part 2 of the tutorial
sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml
cp main.go.time main.go
# [docs:docker-run-update]
rockcraft pack
rockcraft.skopeo --insecure-policy \
copy oci-archive:go-hello-world_0.2_amd64.rock \
docker-daemon:go-hello-world:0.2
docker images go-hello-world:0.2
docker run --rm -d -p 8000:8000 \
--name go-hello-world go-hello-world:0.2
# [docs:docker-run-update-end]
retry -n 5 --wait 2 curl --fail localhost:8000
# [docs:curl-time]
curl --fail localhost:8000/time
# [docs:curl-time-end]
[ "$(curl localhost:8000/time)" != "Hello, world!" ]
# [docs:stop-docker-updated]
docker stop go-hello-world
docker rmi go-hello-world:0.2
# [docs:stop-docker-updated-end]
# [docs:cleanup]
# delete all the files created during the tutorial
rm go.mod rockcraft.yaml main.go go-hello-world \
go-hello-world_0.1_amd64.rock \
go-hello-world_0.2_amd64.rock
# [docs:cleanup-end]
Loading

0 comments on commit 521c3f7

Please sign in to comment.