-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
179 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
defmodule MyPlug do | ||
import Plug.Conn | ||
|
||
def init(options) do | ||
# initialize options | ||
options | ||
end | ||
|
||
def call(conn, _opts) do | ||
conn | ||
|> put_resp_content_type("text/plain") | ||
|> send_resp(200, "Hello world") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#!/usr/bin/env elixir | ||
|
||
Mix.install([:plug, :bandit, :websock_adapter]) | ||
|
||
defmodule EchoServer do | ||
def init(options) do | ||
{:ok, options} | ||
end | ||
|
||
def handle_in({"ping", [opcode: :text]}, state) do | ||
{:reply, :ok, {:text, "pong"}, state} | ||
end | ||
|
||
def terminate(:timeout, state) do | ||
{:ok, state} | ||
end | ||
end | ||
|
||
defmodule Router do | ||
use Plug.Router | ||
|
||
plug Plug.Logger | ||
plug :match | ||
plug :dispatch | ||
|
||
get "/" do | ||
send_resp(conn, 200, """ | ||
Use the JavaScript console to interact using websockets | ||
sock = new WebSocket("ws://localhost:4000/websocket") | ||
sock.addEventListener("message", console.log) | ||
sock.addEventListener("open", () => sock.send("ping")) | ||
""") | ||
end | ||
|
||
get "/websocket" do | ||
conn | ||
|> WebSockAdapter.upgrade(EchoServer, [], timeout: 60_000) | ||
|> halt() | ||
end | ||
|
||
match _ do | ||
send_resp(conn, 404, "not found") | ||
end | ||
end | ||
|
||
require Logger | ||
webserver = {Bandit, plug: Router, scheme: :http, port: 4000} | ||
{:ok, _} = Supervisor.start_link([webserver], strategy: :one_for_one) | ||
Logger.info("Plug now running on http://localhost:4000") | ||
Process.sleep(:infinity) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/bin/bash | ||
|
||
# After opening a Wireguard connection to your Fly network, run this script to | ||
# open a BEAM Observer from your local machine to the remote server. This creates | ||
# a local node that is clustered to a machine running on Fly. | ||
|
||
# In order for it to work: | ||
# - Your wireguard connection must be up. | ||
# - The COOKIE value must be the same as the cookie value used for your project. | ||
# - Observer needs to be working in your local environment. That requires WxWidget support in your Erlang install. | ||
|
||
# When done, close Observer. It leaves you with an open IEx shell that is connected to the remote server. You can safely CTRL+C, CTRL+C to exit it. | ||
|
||
# COOKIE NOTE: | ||
# ============ | ||
# You can explicitly set the COOKIE value in the script if you prefer. That would look like this. | ||
# | ||
# COOKIE=YOUR-COOKIE-VALUE | ||
|
||
set -e | ||
|
||
if [ -z "$COOKIE" ]; then | ||
echo "Set the COOKIE your project uses in the COOKIE ENV value before running this script." | ||
exit 1 | ||
fi | ||
|
||
if ! command -v jq &> /dev/null; then | ||
echo "jq is not installed. Please install it before running this script. It is a command-line JSON processor." | ||
exit 1 | ||
fi | ||
|
||
# Get the data we need in JSON format | ||
json_data=$(fly status --json) | ||
|
||
# Extract app name | ||
app_name=$(echo "$json_data" | jq -r '.Name') | ||
|
||
# Extract private_ip for the first started machine | ||
private_ip=$(echo "$json_data" | jq -r '.Machines[] | select(.state == "started") | .private_ip' | head -n 1) | ||
|
||
# Extract image_ref tag hash for the first started machine | ||
image_tags=$(echo "$json_data" | jq -r '.Machines[] | select(.state == "started") | .image_ref.tag | sub("deployment-"; "")' | head -n 1) | ||
|
||
if [ -z "$private_ip" ]; then | ||
echo "No instances appear to be running at this time." | ||
exit 1 | ||
fi | ||
|
||
# Assemble the full node name | ||
FULL_NODE_NAME="${app_name}-${image_tags}@${private_ip}" | ||
echo Attempting to connect to $FULL_NODE_NAME | ||
|
||
# IMPORTANT: | ||
# ========== | ||
# Fly.io uses an IPv6 network internally for private IPs. The BEAM needs IPv6 | ||
# support to be enabled explicitly. | ||
# | ||
# The issue is, if it's enabled globally like in a `.bashrc` file, then setting | ||
# it here essentially flips it OFF. If not set globally, then it should be set | ||
# here. Choose the version that fits your situation. | ||
# | ||
# It's the `--erl "-proto_dist inet6_tcp"` portion. | ||
|
||
# Toggles on IPv6 support for the local node being started. | ||
iex --erl "-proto_dist inet6_tcp" --sname my_remote --cookie ${COOKIE} -e "IO.inspect(Node.connect(:'${FULL_NODE_NAME}'), label: \"Node Connected?\"); IO.inspect(Node.list(), label: \"Connected Nodes\"); :observer.start" | ||
|
||
# Does NOT toggle on IPv6 support, assuming it is enabled some other way. | ||
# iex --sname my_remote --cookie ${COOKIE} -e "IO.inspect(Node.connect(:'${FULL_NODE_NAME}'), label: \"Node Connected?\"); IO.inspect(Node.list(), label: \"Connected Nodes\"); :observer.start" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#!/usr/bin/env elixir | ||
|
||
Mix.install([:plug, :plug_cowboy]) | ||
|
||
defmodule MyPlug do | ||
import Plug.Conn | ||
|
||
def init(options) do | ||
# initialize options | ||
options | ||
end | ||
|
||
def call(conn, _opts) do | ||
conn | ||
|> put_resp_content_type("text/plain") | ||
|> send_resp(200, "Hello world") | ||
end | ||
end | ||
|
||
require Logger | ||
webserver = {Plug.Cowboy, plug: MyPlug, scheme: :http, options: [port: 4000]} | ||
{:ok, _} = Supervisor.start_link([webserver], strategy: :one_for_one) | ||
Logger.info("Plug now running on localhost:4000") | ||
Process.sleep(:infinity) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
defmodule MyPlugTest do | ||
use ExUnit.Case, async: true | ||
use Plug.Test | ||
|
||
@opts MyPlug.init([]) | ||
|
||
test "returns hello world" do | ||
# Create a test connection | ||
conn = conn(:get, "/hello") | ||
|
||
# Invoke the plug | ||
conn = MyPlug.call(conn, @opts) | ||
|
||
# Assert the response and status | ||
assert conn.state == :sent | ||
assert conn.status == 200 | ||
assert conn.resp_body == "Hello world" | ||
end | ||
end |