Skip to content
/ sapper Public

Sapper is a CLI tool written in Go that enables you to rapidly create, extend, and update C++ microservices

License

Notifications You must be signed in to change notification settings

seboste/sapper

Repository files navigation

Sapper

WARNING: Sapper is still under development. Breaking changes can occur at any time.

Sapper is CLI tool that enables you to rapidly create, extend, and update C++ microservices. It is based on an ever growing template repository --- the brick repo --- with a focus on cloud native technology from which you can compose your microservices, e.g.:

  • http and gRPC handler
  • postgreSQL database
  • JWT based authentication
  • docker and kubernetes
  • support for AWS, Azure, and GCP
  • ...

hexagonal architecture diagram

Foundation

Besides using C++, the microservices that can be created with Sapper are constrained by the following:

Linux AMD64

Sapper and the microservices created with it have a built in support for Linux on AMD64. No efforts are planned to support other platforms. On Windows, the usage of wsl is recommended.

Hexagonal architecture

The structure of each microservice follows the hexagonal -- aka ports & adapters -- architecture: hexagonal architecture diagram

Layer Desription Depends on
ports Domain entities and interfaces that the core needs to work with. -
core Contains all business logic without directly depending on any infrastructure (e.g. databases). ports
adapters Implementation of the interfaces defined in the ports layer. Adapters should be independent from each other, but often rely on third party libraries. ports, external libraries
app The main application that brings everything together: Reads configuration, instantiates the core, instantiates the adapters, injects the adapters into the core, calls the handler. core, adapters

Conan package manager

Dependencies on 3rd party libraries are managed by the conan package manager. Thus, each microservices has a conanfile.txt in its root folder.

Make

Each microservice contains a Unix Makefile in its root folder that allows to build, test, and deploy the service. Sapper uses the GNU make command during some operations. By default CMake and CTest are used for building and testing a microservice, respectively.

Microservice-Essentials library

The Microservice Essentials library implements or facilitates the implementation of cross cutting concepts in microservices such as request handling, observability, error handling, and many more. The cmd and many of the adapters depend on this library, which in turn has no transitive dependencies by design.

Getting started

  1. Make sure that Conan v1.x, CMake, make, and a C++ toolchain (e.g. clang, gcc) is available in your linux build environment. If that's the case, the following commands run without problems:

    conan --version
    cmake --version
    make --version
    gcc --version    #alternative 1
    clang --version  #alternative 2
  2. Install Go by e.g. running:

    wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz
    rm -rf /usr/local/go 
    tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz
    export PATH=$PATH:/usr/local/go/bin
    go version
  3. Install Sapper:

    go install github.com/seboste/sapper@latest
    export PATH=$PATH:~/go/bin
    sapper version
  4. Create your first Sapper C++ microservice:

    sapper service add my-service
    cd my-service    
    sapper brick add handler-http
    sapper brick add observability-structured-logging
    sapper brick add repo-in-memory
    make build

    INFO: hit enter when prompted to specify parameters. It is recommended to execute the commands in a git repository directory and commit the changes after executing each line. In that way, changes made by Sapper can be reconstructed easily.

    The just created service has a http handler that exposes two example REST endpoints, one for setting and one for getting an example entity. Logs are written to standard output in JSON format. The entities are managed in memory by a simple C++ map.

  5. Run and test your service:

    export LOG_LEVEL=TRACE
    make run

    The service is now up and running. You can now call the service from a different terminal:

    curl -X PUT localhost:8080/Entity/test -H "Content-Type: application/json" -d'{"id":"test","string_property":"str","int_property":42}'
    curl localhost:8080/Entity/test

    An example entity has been stored in and retrieved again from the service. As tracing has been turned on, extensive logs have been written to the console.

  6. Add your business code to the core and adapt the ports and adapters to your needs. Voilà, your first C++ microservice is ready.

Main Features

Create Microservices

A new Sapper C++ microservice can be created by running the

sapper service add <servicename>

command. This will create a new directory containing the initial hexagonal microservice structure along with a conanfile.txt to manage dependencies, a CMakeLists.txt, and a Makefile. Many source files include code lines that define so called sapper sections:

//<<<SAPPER SECTION BEGIN **SOME_SECTION_NAME**>>>
...
//<<<SAPPER SECTION END **SOME_SECTION_NAME**>>>

Sapper uses them to identify code areas that may need to be replaced, merged, appended, or prepended by when adding new sapper bricks to the microservice. Modify them only with caution as it might impede sapper.

You can build and execute the service with the following commands:

cd <servicename>
sapper service build .
make run

As this microservice only contains example ports and a simple example core, the executable returns immediately. You need at least one handler and a repository (aka a DB) for your microservice to do something somewhat meaningful.

Extend Microservices

New features (e.g. handlers, databases, notifiers, security, observability, deployment, ...) can be added to a Sapper C++ microservices by adding so called bricks. Use the following command to get a complete list of available bricks including the unique identifier, the version, and a brief description of each brick:

sapper brick list

Then add the desired brick to your microservice:

sapper brick add <brickname>

and enter values for parameters when prompted. New code from the brick library is added to the microservice's codebase (typically by adding another adapter) and integrated into the microservices codebase (typically by adding a few lines of code to the main.cpp in the app folder and adding dependencies to 3rd party libs to the conanfile.txt).

INFO: Bricks assume that the ports are unchanged by the developer, i.e. the microservice works on that example entity mentioned earlier. Thus, it is recommended to first add the desired bricks to your microservice and then adapt the code to your needs and not the other way around. You can still add bricks later, but adding some of the files may fail and more manual work may be required.

INFO: CI ensures that the microservice can be built successfully out of the box when adding a single brick to the initial microservice. However, it is not guaranteed that all possible combinations of bricks can be built successfully (e.g. due to dependency clashes). Some manual fixes may be required.

Update Dependencies

A regular maintenance task for developers is to update the dependencies. For security reasons and because frequent small increments typically are less error prone and work intense than infrequent big increments, this task should be done often. Sapper can facilitate this process by running the command

sapper service upgrade .

It will build the service, identify which dependencies are not up to date, and then in a bisection method update each dependency until the highest dependency library version is identified for which the build process without code changes is successful.

Customize Sapper

Sapper obtains the brick library from a github repository. This is https://github.com/seboste/sapper-bricks by default. Sapper allows to replace or extend the brick library or replace individual bricks by managing remotes. Call

sapper remote --help

for more details. This can for example be useful for organizations that want to provide custom C++ microservice templates to be used by all teams of that organization. Please refer to https://github.com/seboste/sapper-bricks's README.md for details on how to create your own Sapper bricks.

INFO: Sapper can only be as good as the underlying brick library. If you create bricks that may be useful to the general public, please consider contributing by creating a pull request to https://github.com/seboste/sapper-bricks.

Reference

For a complete description of the commands and subcommands please refer to the tool's help:

sapper --help
sapper <command> --help

About

Sapper is a CLI tool written in Go that enables you to rapidly create, extend, and update C++ microservices

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages