Skip to content

Commit 72481e3

Browse files
authored
fix: add hello-haproxy (#69)
Incorporates the [`hello-haproxy`](https://github.com/launchdarkly/hello-haproxy) example directly into the repo so it can be continually tested and kept up-to-date.
1 parent 934c5ca commit 72481e3

File tree

6 files changed

+158
-4
lines changed

6 files changed

+158
-4
lines changed

.github/workflows/ci.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,24 @@ jobs:
4040
with:
4141
lua-version: ${{ matrix.version }}
4242
rockspec: ${{ matrix.package }}
43+
44+
45+
hello-haproxy:
46+
runs-on: ubuntu-latest
47+
env:
48+
LD_SDK_KEY: "foo"
49+
steps:
50+
- uses: actions/checkout@v4
51+
- name: Build hello-haproxy image
52+
run: |
53+
docker build -t launchdarkly:hello-haproxy -f ./examples/hello-haproxy/Dockerfile .
54+
- name: Run hello-haproxy container in background
55+
run: |
56+
docker run -dit --rm --name hello-haproxy -p 8123:8123 --env LD_SDK_KEY="$LD_SDK_KEY" launchdarkly:hello-haproxy
57+
- name: Evaluate feature flag
58+
run: |
59+
curl --retry 5 --retry-all-errors --retry-delay 1 -s -v http://localhost:8123 | tee response.txt
60+
grep -F "Feature flag is false for this user" response.txt || (echo "Expected false evaluation!" && exit 1)
61+
- name: Stop hello-haproxy container
62+
run: |
63+
docker stop hello-haproxy

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,29 @@ Getting started
4949
Refer to the [SDK documentation](https://docs.launchdarkly.com/sdk/server-side/lua#getting-started) for instructions on
5050
getting started with using the SDK.
5151

52+
The following examples are available in addition to the usage guide linked above:
53+
54+
55+
| Example | Purpose |
56+
|-------------------------------------------------|-----------------------------------------------------------------------------------------------|
57+
| [hello-lua-server](./examples/hello-lua-server) | Demonstrates basic example of Lua SDK usage from the command line. |
58+
| [hello-haproxy](./examples/hello-haproxy) | Demonstrates usage of the Lua SDK as a [HAproxy](https://www.haproxy.org/) module via Docker. |
59+
60+
61+
Before you start using the SDK, you'll need to install it.
62+
5263
There are two paths to installing the SDK. In both cases, you must first install the native
5364
[LaunchDarkly C++ Server-side SDK](https://github.com/launchdarkly/cpp-sdks).
5465

5566
You may build the C++ SDK from source using [CMake](https://cmake.org/), or obtain pre-built artifacts from the
5667
[releases page](https://github.com/launchdarkly/cpp-sdks/releases?q=%22launchdarkly-cpp-server%22). Ensure you install
57-
the correct variant (with or without Redis support) as necessary.
68+
the correct variant (with or without Redis support) as defined by your requirements.
5869

5970
Please note that the Lua SDK uses the C++ server-side SDK's C bindings, so if you're using prebuilt artifacts
6071
then only a C99 compiler is necessary. See the [Build Requirements](https://github.com/launchdarkly/cpp-sdks#build-requirements).
6172

6273

63-
Then, install the [LuaRocks](https://github.com/luarocks/luarocks/wiki/Download) package manager.
74+
Once the C++ SDK is available, install the [LuaRocks](https://github.com/luarocks/luarocks/wiki/Download) package manager.
6475

6576
### Install via `luarocks install`
6677

@@ -81,7 +92,7 @@ LDREDIS_DIR=./path-to-cpp-sdk-with-redis-support-installation
8192

8293
### Install via `luarocks make`
8394

84-
If you don't want to install from LuaRocks, it's possible to compile the modules locally using `luarocks make`.
95+
If you don't want to install from LuaRocks, it's possible to compile the modules locally in this git repo by using `luarocks make`.
8596

8697
**Install the base SDK only**
8798
```bash
@@ -103,7 +114,7 @@ Read our [documentation](https://docs.launchdarkly.com) for in-depth instruction
103114
Testing
104115
-------
105116

106-
We run integration tests for all our SDKs using a centralized test harness. This approach gives us the ability to test for consistency across SDKs, as well as test networking behavior in a long-running application. These tests cover each method in the SDK, and verify that event sending, flag evaluation, stream reconnection, and other aspects of the SDK all behave correctly.
117+
We run integration tests for all our SDKs using a centralized test harness. This approach gives us the ability to test for consistency across SDKs. These tests cover each method in the SDK, and verify that event sending, flag evaluation, stream reconnection, and other aspects of the SDK all behave correctly.
107118

108119
Contributing
109120
------------

examples/hello-haproxy/Dockerfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
FROM ubuntu:22.04
2+
3+
RUN apt-get update && apt-get install -y \
4+
curl luarocks lua5.3 lua5.3-dev \
5+
haproxy apt-transport-https ca-certificates \
6+
software-properties-common
7+
8+
RUN add-apt-repository ppa:mhier/libboost-latest && \
9+
apt-get update && \
10+
apt-get install -y boost1.81
11+
12+
RUN curl https://github.com/launchdarkly/cpp-sdks/releases/download/launchdarkly-cpp-server-v3.3.1/linux-gcc-x64-dynamic.zip -L -o /tmp/sdk.zip && \
13+
mkdir ./cpp-sdk && \
14+
unzip /tmp/sdk.zip -d ./cpp-sdk && \
15+
rm /tmp/sdk.zip
16+
17+
COPY . .
18+
19+
RUN luarocks make launchdarkly-server-sdk-2.0.2-0.rockspec LD_DIR=./cpp-sdk/build-dynamic/release
20+
21+
COPY ./examples/hello-haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
22+
COPY ./examples/hello-haproxy/service.lua /service.lua
23+
24+
# The strategy for this Docker example is to download the C++ SDK release artifacts and use those instead of compiling
25+
# from source. This is for example/CI purposes only; generally it's better to build from source to ensure all libraries
26+
# are compatible.
27+
#
28+
# Since we require a newer version of boost than is available in Ubuntu 22.04, we grab it from a PPA (mhier/libboost-latest).
29+
#
30+
# The SDK dynamic libs expect the boost libs to follow a specific naming convention, which isn't what
31+
# the libraries from the PPA follow ('-mt' suffix is added to indicate the libraries are built with multithreading support enabled.)
32+
#
33+
# It's not 100% clear if these libraries are multithread enabled (build logs in the PPA seem to indicate it),
34+
# but even so, the C++ SDK is single-threaded.
35+
#
36+
# To workaround, add symlinks with the expected names.
37+
RUN cd /usr/lib/x86_64-linux-gnu && \
38+
ln -s libboost_json.so.1.81.0 libboost_json-mt-x64.so.1.81.0 && \
39+
ln -s libboost_url.so.1.81.0 libboost_url-mt-x64.so.1.81.0
40+
41+
CMD haproxy -d -f /etc/haproxy/haproxy.cfg

examples/hello-haproxy/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# LaunchDarkly Lua server-side SDK HAProxy example
2+
3+
We've built a minimal dockerized example of using the Lua SDK with [HAProxy](https://www.haproxy.org/). For more comprehensive instructions, you can visit the [Using the Lua SDK with HAProxy guide](https://docs.launchdarkly.com/guides/sdk/haproxy) or the [Lua reference guide](https://docs.launchdarkly.com/sdk/server-side/lua).
4+
5+
## Build instructions
6+
7+
1. On the command line from the root of the repo, build the image from this directory with `docker build -t hello-haproxy -f ./examples/hello-haproxy/Dockerfile .`.
8+
2. Run the demo with:
9+
```
10+
docker run -it --rm --name hello-haproxy -p 8123:8123 --env LD_SDK_KEY="your-sdk-key" --env LD_FLAG_KEY="my-boolean-flag" hello-haproxy```
11+
```
12+
3. **Note:** the SDK key and flag key are passed with environment variables into the container. The `LD_FLAG_KEY` should be a boolean-type flag in your environment.
13+
4. Open `localhost:8123` in your browser. Toggle the flag on to see a change in the page (refresh the page.)
14+
15+
You should receive the message:
16+
> Feature flag is <true/false> for this user.

examples/hello-haproxy/haproxy.cfg

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
global
2+
lua-load /service.lua
3+
4+
defaults
5+
mode http
6+
timeout connect 10s
7+
timeout client 30s
8+
timeout server 30s
9+
10+
frontend proxy
11+
bind 0.0.0.0:8123
12+
use_backend default_backend
13+
14+
backend default_backend
15+
http-request use-service lua.launchdarkly

examples/hello-haproxy/service.lua

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
print "loaded"
2+
3+
local os = require("os")
4+
local ld = require("launchdarkly_server_sdk")
5+
6+
7+
-- Set YOUR_SDK_KEY to your LaunchDarkly SDK key.
8+
local YOUR_SDK_KEY = ""
9+
10+
-- Set YOUR_FEATURE_KEY to the feature flag key you want to evaluate.
11+
local YOUR_FEATURE_KEY = "my-boolean-flag"
12+
13+
14+
-- Allows the LaunchDarkly SDK key to be specified as an environment variable (LD_SDK_KEY)
15+
-- or locally in this example code (YOUR_SDK_KEY).
16+
function get_key_from_env_or(name, existing_key)
17+
if existing_key ~= nil and existing_key ~= "" then
18+
core.Debug("Using LaunchDarkly SDK key from service.lua file")
19+
return existing_key
20+
end
21+
22+
local env_key = os.getenv("LD_" .. name)
23+
if env_key ~= nil and env_key ~= "" then
24+
core.Debug("Using LaunchDarkly SDK key from LD_" .. name .. " environment variable")
25+
return env_key
26+
end
27+
28+
core.log(core.crit, "LaunchDarkly SDK key not provided! SDK won't be initialized.")
29+
return ""
30+
end
31+
32+
local config = {}
33+
local client = ld.clientInit(get_key_from_env_or("SDK_KEY", YOUR_SDK_KEY), 1000, config)
34+
35+
core.register_service("launchdarkly", "http", function(applet)
36+
applet:start_response()
37+
38+
local user = ld.makeContext({
39+
user = {
40+
key = "example-user-key",
41+
name = "Sandy"
42+
}
43+
})
44+
45+
if client:boolVariation(user, get_key_from_env_or("FLAG_KEY", YOUR_FEATURE_KEY), false) then
46+
applet:send("<p>Feature flag is true for this user</p>")
47+
else
48+
applet:send("<p>Feature flag is false for this user</p>")
49+
end
50+
end)

0 commit comments

Comments
 (0)