AOSharedServiceLibrary
How to Use the AO Shared Service Library

TieredApplicationProfile

The TieredApplicationProfile class provides a means of automatic configuration from a variety of sources. Let's take a look at a profile to read from Command Line options and Environment Variables:

#include <iostream>
#include <string>
#include "include/tiered_app_profile.h"

int main(int argc, char** argv) {
    AOSSL::TieredApplicationProfile profile(argc, argv, \
      std::string("MyApplication"), std::string("MyProfile"));

    std::string key = "testKey";
    profile.add_opt(key, std::string("defaultValue"));

Thus far, we've created a new TieredApplicationProfile, passing in 4 arguments to the constructor. First, we pass in both arguments from the main method, to be parsed. Then, we provide an Application Name and Profile Name (we'll see how these get used in a few moments). Finally, we call add_opt to inform the profile of a key to search for, as well as it's default value.

Next, let's add some additional configuration sources to the profile:

    profile.set_property_file(std::string("test/test.properties"));
    profile.set_consul_address("localhost:8500");

Here, we've specified both a configuration file, as well as a network address at which we can reach a Consul Agent. Calling these methods prior to loading the configuration is not required, so you can use any combination of the config sources. If you don't want to use Command Line Arguments, you can call an alternative constructor passing only the application and profile name.

Alternatively, we can pass any of the following arguments, which will trigger pulling from a configuration source:

Command Line/Properties File

Environment Variables

Properties File

Default Sources

By default, the profile will look for the following default sources, and use them if available:

Please see the Consul Documentation for more information on setting up an agent (https://www.consul.io/docs/agent/basics.html). Docker can also be used to start a Consul Agent (https://hub.docker.com/_/consul/).

Our next step is to call load_config(), which will go out to the various sources and populate the specified values in an internal hash map (std::unordered_map). This ensures that runtime access of configuration elements happens in constant time.

Note that the profile will only search for keys that have been specified with add_opt().

    profile.load_config();

Values will be populated with the following priority:

Accessing the values once they've been populated is quite simple:

    AOSSL::StringBuffer buf;
    if (profile.opt_exist(key)) {
        profile.get_opt(key, buf);
        std::cout << buf.val << std::endl;
    }
}

Thread-Safety

Retrieving and writing values to the application profile is thread-safe. Updating profile sources is safe to perform from a unique thread, and other threads can continue to access the KV Store. You will have issues if, for example, one thread calls load_config(), and another tries to update the consul address at the same time.

Secure Application Properties

During configuration, applications often need to load sensitive and/or secure values. These are supported by integration with Hashicorp Vault.

Prior to calling load_config(), we can call add_secure_opt(std:string& key). This informs the application profile that it needs to look for secure properties. Secure properties are loaded from three sources:

Please note that environment variables and properties file values are loaded for debug purposes only, and should not be used in production scenarios.

Vault connectivity information can be set via environment variables, command line values, or separate files. The SSL Certificate can be left out to disable HTTPS, but this should never be done in a production environment.

The Tiered Application Profile is coded to v2 of the Vault KV API. Please ensure that any instance of Vault being used has either Username/Password or AppRole authentication enabled, as well as the V2 KV API enabled.

Command Line/Properties File

Environment Variables

Secret Files

The Vault Username/Role ID and Password/Secred ID can both be provided via a separate file. This is the recommendation of Hashicorp, as command line arguments are often stored in shell histories. These files are intended to be injected into the environment of an executable prior to be startup, by some other process.

Keep in mind that these will override any CLI/Environment Variables provided, and will need to have at least a vault address and auth type specified.

Service Component Factories

The Service Component Factories are components which allow us to build instances of the interfaces exposed by the library. These can be used to build individual instances of the underlying components, rather than using an ApplicationProfile.

It's important that we use the factory to get instances of the interfaces as the interfaces guarantee backwards-compatibility. While particular implementations may change, the interfaces will remain the same across major versions of the library. For example:

#include "aossl/commandline/include/factory_cli.h"
#include "aossl/core/include/kv_store_interface.h"

// Set up a Service Component Factory, where we get our application components
AOSSL::CommandLineInterpreterFactory cli_factory;

The factory then provides us access to instances of the interfaces exposed by the library.

AOSSL::KeyValueStoreInterface *cli = cli_factory.get_command_line_interface( argc, argv );

Note: Be sure to delete anything you build with the factories! Due to the nature of C++ and a desire to retain flexibility, AOSSL is implemented such that it hands over responsibility for the memory allocated to the end user whenever a factory call is made.

Tools

A Variety of tools are provided by AOSSL, all of which are thread safe.

Compilation

Please continue on to the Compilation section of the documentation to learn about building an application with the library.

Go Home