Microservices automated testing and local development
Using Roxy in your backend for your automated testing and local development flow
This page describes the challenge and solution for dealing with feature
flags in local development and automated testing in a microservice
architecture. It shows how you can use Roxy
, a Docker image that mocks
CloudBees Feature Management storage and provides REST API to control flag behavior on local
development or for automated testing (creating flag behavior fixture,
controlling the flag values, etc…).
Understanding feature flags in the microservice architecture
What are microservices? "In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies." — James Lewis and Martin Fowler |
Contrary to common belief, Feature flags should not be a standalone service in your environment. Adding a Feature flagging microservice does not follow the guidelines of microservice architecture, and introduces the following architectural flows:
-
The Feature Flags service is not a vertical service - choosing the flag service approach is more suitable for SOA and not microservices architecture
-
Feature flags evaluation latency is dependant on the network topography and feature flags service load
-
Other services are not independently deployable because of coupling with feature flags microservices
Some of these issues can be solved by an implementing a caching layer on the consumer microservices, but this solution introduces more complexity and fragility into the system. It is better to choose the right architecture, a distributed one.
In a distributed solution the Feature Flags SDK is installed on the relevant microservice, the SDK uses CloudBees Feature Management storage to get the flags configuration but a connection is not required when evaluating flags. Here is a diagram that demonstrates this Architecture:
Microservices Architecture Diagram
As you can see, the SDK is installed on the microservices and fetches the configuration from CloudBees Feature Management storage. Calculating whether a flag is enabled/disabled is done in local memory with a distributed algorithm, thus solving all the architectural flaws described above.
The issue with automated testing
Not Unit testing This section does not describe how to unit test, it is focused on automated acceptance testing that is done on the entire microservice environment (or parts of it). |
The above diagram shows the desired architecture for a feature flag enabled environment. As you can see the Feature Flag SDK runs on multiple instances of multiple microservices. Each microservice consumes different or shared flags.
When writing tests for this environment, you first need to set up the fixture of the test. The test fixture includes setting up various components, loading relevant data into the database and setting flag values.
When we set flag values we want to know as little as possible on the
system, to eliminate any dependencies to implementation that will make
the test fragile. In order to do so, CloudBees Feature Management has released a component
called Roxy. Roxy
is a docker image that mocks CloudBees Feature Management storage and
provides REST API to control flags behavior in a non production
environment.
The issue with local development
When developing a service, the developer is often required to set a flag
value for their specific localhost environment, these flags can be
consumed on the service they are developing or on other services in
their environment.
It is not the developer’s concern to understand which flags are
consumed by which microservice and how many instances each microservice
is running. To hide these implementation details from the developer it
is required to have a single point of abstraction to set up flags value
across the environment
To allow the developer to control the flags values on their development
environment, CloudBees Feature Management has released a component called Roxy. Roxy
is a
docker image that mocks CloudBees Feature Management storage and provides REST API to control
flag behavior in a non production environment.
Roxy architecture view
Roxy replaces CloudBees Feature Management storage and runs from inside your domain, in practice it supplies a mock service on top of CloudBees Feature Management software as a service solution. Here is how Roxy fits into the microservice diagram
As can be seen above, the CloudBees Feature Management SDK that is running on each microservice does the configuration fetching from Roxy instead of CloudBees Feature Management storage.
Running Roxy
Roxy is distributed as a docker image. Roxy listens on port 3333
Here is how you run it with the docker command line:
docker run -p 4444:3333 -d rollout/roxy:latest
This command will start Roxy inside the container and will expose port 4444 as Roxy port. The next step is to configure CloudBees Feature Management SDK to work with Roxy as its configuration source.
Redirecting the SDK to Roxy
Configure the CloudBees Feature Management SDK to work with Roxy as its configuration source:
Java | Node.js | JavaScript SSR | .NET | Python | Go | Ruby | PHP | C | C++ |
---|---|---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
After setting this withRoxyUrl
configuration the SDK will fetch its
configuration from localhost:4444
Supported on SDK 3.2.0 and higher This withRoxyUrl configuration is supported on Java SDK from version 3.2.0 |
Controlling flags via REST API
Roxy supports the following REST API for setting flags values:
-
GET /flags/<flagname>
- get flag behavior -
GET /flags/
- get all flags behavior -
POST /flags/<flagname>
- set flag behavior within body. To set a flag to true send body:{ expression: “true” }
, to set a flag to false send body:{ expression: “false” }
-
DELETE /flags/<flagname>
- Reset flag behavior -
DELETE /flags/
- Reset all flags behavior
The API is also available via a Swagger interface at
http://localhost:4444/api-docs
.