Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/actions/ci/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ runs:
- name: Run hello-lua-server example
if: ${{ !contains(inputs.lua-version, 'jit') }}
shell: bash
run: ./scripts/interpreter.sh ./examples/hello-lua-server/hello.lua
run: |
cd ./examples/hello-lua-server
lua hello.lua | tee output.txt
grep -F "is false for this user" output.txt || (echo "Expected false evaluation!" && exit 1)
env:
LD_SDK_KEY: "fake-sdk-key"
# Needed because boost isn't installed in default system paths, which is
Expand Down
22 changes: 13 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,26 @@ jobs:
rockspec: ${{ matrix.package }}


hello-haproxy:
examples:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
name: ["hello-haproxy", "hello-nginx"]
env:
LD_SDK_KEY: "foo"
LD_SDK_KEY: foo
steps:
- uses: actions/checkout@v4
- name: Build hello-haproxy image
- name: Build ${{ matrix.name }} image
run: |
docker build -t launchdarkly:hello-haproxy -f ./examples/hello-haproxy/Dockerfile .
- name: Run hello-haproxy container in background
docker build -t launchdarkly:${{ matrix.name }} -f ./examples/${{ matrix.name }}/Dockerfile .
- name: Run ${{ matrix.name }} container in background
run: |
docker run -dit --rm --name hello-haproxy -p 8123:8123 --env LD_SDK_KEY="$LD_SDK_KEY" launchdarkly:hello-haproxy
docker run -dit --rm --name ${{ matrix.name }} -p 8123:80 --env LD_SDK_KEY="$LD_SDK_KEY" launchdarkly:${{ matrix.name }}
- name: Evaluate feature flag
run: |
curl --retry 5 --retry-all-errors --retry-delay 1 -s -v http://localhost:8123 | tee response.txt
grep -F "Feature flag is false for this user" response.txt || (echo "Expected false evaluation!" && exit 1)
- name: Stop hello-haproxy container
grep -F "is false for this user" response.txt || (echo "Expected false evaluation!" && exit 1)
- name: Stop ${{ matrix.name }} container
run: |
docker stop hello-haproxy
docker stop ${{ matrix.name }}
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ getting started with using the SDK.
The following examples are available in addition to the usage guide linked above:


| Example | Purpose |
|-------------------------------------------------|-----------------------------------------------------------------------------------------------|
| [hello-lua-server](./examples/hello-lua-server) | Demonstrates basic example of Lua SDK usage from the command line. |
| [hello-haproxy](./examples/hello-haproxy) | Demonstrates usage of the Lua SDK as a [HAproxy](https://www.haproxy.org/) module via Docker. |
| Example | Purpose |
|-------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| [hello-lua-server](./examples/hello-lua-server) | Demonstrates basic example of Lua SDK usage from the command line. |
| [hello-haproxy](./examples/hello-haproxy) | Demonstrates usage of the Lua SDK as a [HAproxy](https://www.haproxy.org/) module via Docker. |
| [hello-nginx](./examples/hello-nginx) | Demonstrates usage of the Lua SDK as a [nginx OpenResty](https://github.com/openresty/openresty) module via Docker. |


Before you start using the SDK, you'll need to install it.
Expand Down
17 changes: 17 additions & 0 deletions examples/env-helper/get_from_env_or_default.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- This is a helper function to get a value from an existing variable, if not empty or nil, or otherwise
-- from an environment variable.
function get_from_env_or_default(env_variable_name, local_variable)
if local_variable ~= nil and local_variable ~= "" then
return local_variable
end

local env_var = os.getenv(env_variable_name)
if env_var ~= nil and env_var ~= "" then
return env_var
end

return ""
end


return get_from_env_or_default
1 change: 1 addition & 0 deletions examples/hello-haproxy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RUN curl https://github.com/launchdarkly/cpp-sdks/releases/download/launchdarkly
COPY . .
COPY ./examples/hello-haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
COPY ./examples/hello-haproxy/service.lua /service.lua
COPY ./examples/env-helper/get_from_env_or_default.lua /get_from_env_or_default.lua

RUN luarocks make launchdarkly-server-sdk-"${VERSION}"-0.rockspec LD_DIR=./cpp-sdk/build-dynamic/release

Expand Down
8 changes: 4 additions & 4 deletions examples/hello-haproxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ We've built a minimal dockerized example of using the Lua SDK with [HAProxy](htt

## Build instructions

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 .`.
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 .`.
2. Run the demo with:
```
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```
```bash
docker run -it --rm --name hello-haproxy -p 8123:8123 --env LD_SDK_KEY="my-sdk-key" --env LD_FLAG_KEY="my-boolean-flag" hello-haproxy
```
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.
4. Open `localhost:8123` in your browser. Toggle the flag on to see a change in the page (refresh the page.)

You should receive the message:
> Feature flag is <true/false> for this user.
> Feature flag is <true/false> for this user context
2 changes: 1 addition & 1 deletion examples/hello-haproxy/haproxy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defaults
timeout server 30s

frontend proxy
bind 0.0.0.0:8123
bind 0.0.0.0:80
use_backend default_backend

backend default_backend
Expand Down
40 changes: 12 additions & 28 deletions examples/hello-haproxy/service.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,19 @@ print "loaded"

local os = require("os")
local ld = require("launchdarkly_server_sdk")
local get_from_env_or_default = require("get_from_env_or_default")

-- Set MY_SDK_KEY to your LaunchDarkly SDK key.
local MY_SDK_KEY = ""

-- Set YOUR_SDK_KEY to your LaunchDarkly SDK key.
local YOUR_SDK_KEY = ""

-- Set YOUR_FEATURE_KEY to the feature flag key you want to evaluate.
local YOUR_FEATURE_KEY = "my-boolean-flag"


-- Allows the LaunchDarkly SDK key to be specified as an environment variable (LD_SDK_KEY)
-- or locally in this example code (YOUR_SDK_KEY).
function get_key_from_env_or(name, existing_key)
if existing_key ~= nil and existing_key ~= "" then
core.Debug("Using LaunchDarkly SDK key from service.lua file")
return existing_key
end

local env_key = os.getenv("LD_" .. name)
if env_key ~= nil and env_key ~= "" then
core.Debug("Using LaunchDarkly SDK key from LD_" .. name .. " environment variable")
return env_key
end

core.log(core.crit, "LaunchDarkly SDK key not provided! SDK won't be initialized.")
return ""
end
-- Set MY_FLAG_KEY to the boolean-type feature flag key you want to evaluate.
local MY_FLAG_KEY = "my-boolean-flag"

local config = {}
local client = ld.clientInit(get_key_from_env_or("SDK_KEY", YOUR_SDK_KEY), 1000, config)
local sdk_key = get_from_env_or_default("LD_SDK_KEY", MY_SDK_KEY)
local client = ld.clientInit(sdk_key, 1000, config)

local flag_key = get_from_env_or_default("LD_FLAG_KEY", MY_FLAG_KEY)

core.register_service("launchdarkly", "http", function(applet)
applet:start_response()
Expand All @@ -42,9 +26,9 @@ core.register_service("launchdarkly", "http", function(applet)
}
})

if client:boolVariation(user, get_key_from_env_or("FLAG_KEY", YOUR_FEATURE_KEY), false) then
applet:send("<p>Feature flag is true for this user</p>")
if client:boolVariation(user, flag_key, false) then
applet:send("<p>Feature flag " .. flag_key .. " is true for this user context</p>")
else
applet:send("<p>Feature flag is false for this user</p>")
applet:send("<p>Feature flag " .. flag_key .. " is false for this user context</p>")
end
end)
16 changes: 16 additions & 0 deletions examples/hello-lua-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# LaunchDarkly Lua server-side SDK basic example

First, modify `hello.lua` to inject your SDK key and boolean-type feature flag key.

Then, use the Lua interpreter to run `hello.lua`:
```bash
lua hello.lua
```

If you'd rather use environment variables to specify the SDK key or flag key, set `LD_SDK_KEY` or `LD_FLAG_KEY`.
```bash
LD_SDK_KEY=my-sdk-key LD_FLAG_KEY=my-boolean-flag lua hello.lua
```

The program should output:
> Feature flag is <true/false> for this user context
32 changes: 10 additions & 22 deletions examples/hello-lua-server/hello.lua
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
local ld = require("launchdarkly_server_sdk")
local get_from_env_or_default = dofile("../env-helper/get_from_env_or_default.lua")

-- Allows the LaunchDarkly SDK key to be specified as an environment variable (LD_SDK_KEY)
-- or locally in this example code (YOUR_SDK_KEY).
function get_key_from_env_or(existing_key)
if existing_key ~= "" then
return existing_key
end
-- Set MY_SDK_KEY to your LaunchDarkly SDK key.
local MY_SDK_KEY = ""

local env_key = os.getenv("LD_SDK_KEY")
if env_key ~= "" then
return env_key
end

error("No SDK key specified (use LD_SDK_KEY environment variable or set local YOUR_SDK_KEY)")
end

-- Set YOUR_SDK_KEY to your LaunchDarkly SDK key.
local YOUR_SDK_KEY = ""

-- Set YOUR_FEATURE_KEY to the feature flag key you want to evaluate.
local YOUR_FEATURE_KEY = "my-boolean-flag"
-- Set MY_FLAG_KEY to the boolean-type feature flag key you want to evaluate.
local MY_FLAG_KEY = "my-boolean-flag"


local config = {}

local client = ld.clientInit(get_key_from_env_or(YOUR_SDK_KEY), 1000, config)
local sdk_key = get_from_env_or_default("LD_SDK_KEY", MY_SDK_KEY)
local client = ld.clientInit(sdk_key, 1000, config)

local user = ld.makeContext({
user = {
Expand All @@ -33,5 +20,6 @@ local user = ld.makeContext({
}
})

local value = client:boolVariation(user, YOUR_FEATURE_KEY, false)
print("feature flag "..YOUR_FEATURE_KEY.." is "..tostring(value).." for this user")
local flag_key = get_from_env_or_default("LD_FLAG_KEY", MY_FLAG_KEY)
local value = client:boolVariation(user, flag_key, false)
print("Feature flag ".. flag_key .." is "..tostring(value).." for this user context")
56 changes: 56 additions & 0 deletions examples/hello-nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
FROM openresty/openresty:jammy

# {{ x-release-please-start-version }}
ARG VERSION=2.0.6
# {{ x-release-please-end }}

RUN apt-get update && apt-get install -y \
git netbase curl libssl-dev openssl libssl3 openssl apt-transport-https ca-certificates \
software-properties-common \
cmake ninja-build

RUN add-apt-repository ppa:mhier/libboost-latest && \
apt-get update && \
apt-get install -y boost1.81


RUN mkdir cpp-sdk-libs
RUN git clone --branch launchdarkly-cpp-server-v3.3.1 https://github.com/launchdarkly/cpp-sdks.git && \
cd cpp-sdks && \
mkdir build-dynamic && \
cd build-dynamic && \
cmake -GNinja \
-DLD_BUILD_EXAMPLES=OFF \
-DBUILD_TESTING=OFF \
-DLD_BUILD_SHARED_LIBS=ON \
-DLD_DYNAMIC_LINK_OPENSSL=ON .. && \
cmake --build . --target launchdarkly-cpp-server && \
cmake --install . --prefix=../../cpp-sdk-libs

RUN mkdir -p /usr/local/openresty/nginx/scripts

COPY . .
COPY ./examples/hello-nginx/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY ./examples/hello-nginx/shared.lua /usr/local/openresty/nginx/scripts/
COPY ./examples/env-helper/get_from_env_or_default.lua /usr/local/openresty/nginx/scripts/


RUN luarocks make launchdarkly-server-sdk-"${VERSION}"-0.rockspec LD_DIR=./cpp-sdk-libs && \
cp launchdarkly_server_sdk.so /usr/local/openresty/lualib/

# The strategy for this Docker example is to download the C++ SDK release artifacts and use those instead of compiling
# from source. This is for example/CI purposes only; generally it's better to build from source to ensure all libraries
# are compatible.
#
# Since we require a newer version of boost than is available in Ubuntu 22.04, we grab it from a PPA (mhier/libboost-latest).
#
# The SDK dynamic libs expect the boost libs to follow a specific naming convention, which isn't what
# the libraries from the PPA follow ('-mt' suffix is added to indicate the libraries are built with multithreading support enabled.)
#
# It's not 100% clear if these libraries are multithread enabled (build logs in the PPA seem to indicate it),
# but even so, the C++ SDK is single-threaded.
#
# To workaround, add symlinks with the expected names.
RUN cd /usr/lib/x86_64-linux-gnu && \
ln -s libboost_json.so.1.81.0 libboost_json-mt-x64.so.1.81.0 && \
ln -s libboost_url.so.1.81.0 libboost_url-mt-x64.so.1.81.0
16 changes: 16 additions & 0 deletions examples/hello-nginx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# LaunchDarkly Lua server-side SDK NGINX example

We've built a minimal dockerized example of using the Lua SDK with [OpenResty NGINX framework](https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/). For more comprehensive instructions, you can visit the [Using the Lua SDK with NGINX](https://docs.launchdarkly.com/guides/sdk/nginx) guide or the [Lua reference guide](https://docs.launchdarkly.com/sdk/server-side/lua).

## Build instructions

1. On the command line from the **root** of the repo, build the image from this directory with `docker build -t hello-nginx -f ./examples/hello-nginx/Dockerfile .`.
2. Run the demo with
```bash
docker run --rm --name hello-nginx -p 8123:80 --env LD_SDK_KEY="my-sdk-key" --env LD_FLAG_KEY="my-boolean-flag" hello-nginx
```
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.
4. Open `localhost:8123` in your browser. Toggle the flag on to see a change in the page (refresh the page.)

You should receive the message:
> Feature flag is <true/false> for this user context
48 changes: 48 additions & 0 deletions examples/hello-nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
events {
worker_connections 1024;
}

env LD_SDK_KEY;
env LD_FLAG_KEY;

http {
resolver 8.8.8.8;

lua_package_path ";;/usr/local/openresty/nginx/scripts/?.lua;";

init_worker_by_lua_file scripts/shared.lua;

server {
location / {
default_type text/html;

content_by_lua_block {
local os = require("os")
local ld = require("launchdarkly_server_sdk")
local client = require("shared")
local get_from_env_or_default = require("get_from_env_or_default")


-- Set MY_FLAG_KEY to the feature flag key you want to evaluate. To specify the flag key as
-- an environment variable instead, set LD_FLAG_KEY using '--env LD_FLAG_KEY=my-boolean-flag-key'
-- as a 'docker run' argument.

local MY_FLAG_KEY = "my-boolean-flag"

local user = ld.makeContext({
user = {
key = "example-user-key",
name = "Sandy"
}
})

local flag_key = get_from_env_or_default("LD_FLAG_KEY", MY_FLAG_KEY)
if client:boolVariation(user, flag_key, false) then
ngx.say("<p>Feature flag " .. flag_key .. " is true for this user context</p>")
else
ngx.say("<p>Feature flag " .. flag_key .. " is false for this user context</p>")
end
}
}
}
}
11 changes: 11 additions & 0 deletions examples/hello-nginx/shared.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
local ld = require("launchdarkly_server_sdk")
local os = require("os")
local get_from_env_or_default = require("get_from_env_or_default")

-- Set MY_SDK_KEY to your LaunchDarkly SDK key. To specify the SDK key as an environment variable instead,
-- set LD_SDK_KEY using '--env LD_SDK_KEY=my-sdk-key' as a 'docker run' argument.
local MY_SDK_KEY = ""

local config = {}

return ld.clientInit(get_from_env_or_default("LD_SDK_KEY", MY_SDK_KEY), 1000, config)