Skip to content
This repository was archived by the owner on Oct 31, 2021. It is now read-only.

Commit fba4ff8

Browse files
committed
Improvements around running the API locally.
1 parent 893220c commit fba4ff8

File tree

6 files changed

+52
-165
lines changed

6 files changed

+52
-165
lines changed

.helmignore

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ node_modules
2525
generated
2626
tools
2727
pkg
28+
*.sock

Makefile.local

+9-23
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ JQ=jq
1313
KUBECTL=kubectl
1414
SPLIT_YAML=kubernetes-split-yaml
1515
SSHFS=sshfs
16-
TELEPRESENCE=telepresence
1716
YQ=yq
1817

1918
# This is the domain that is used for local development. You can change it to anything you want here and run init-mini
@@ -158,6 +157,7 @@ init-mini-values: $(LOGIN_JWT_SECRET) $(REGISTER_JWT_SECRET)
158157
yq e '.ingress.annotations."kubernetes.io/ingress.class" = "nginx"' -i $(VALUES)
159158
yq e '.ingress.hosts[0].host = "api.$(LOCAL_DOMAIN)"' -i $(VALUES)
160159
yq e '.ingress.hosts[0].paths[0] = {"path": "/"}' -i $(VALUES)
160+
yq e '.service.port = 4000' -i $(VALUES)
161161
yq e '.api.includeSecrets = true' -i $(VALUES)
162162
yq e '.api.uiDomainName = "app.$(LOCAL_DOMAIN)"' -i $(VALUES)
163163
yq e '.api.apiDomainName = "api.$(LOCAL_DOMAIN)"' -i $(VALUES)
@@ -198,16 +198,14 @@ deploy-postgres:
198198
$(KUBECTL) apply -f $(PWD)/minikube/postgres.yaml --namespace $(MINIKUBE_NAMESPACE)
199199
$(KUBECTL) rollout status deploy/postgres --namespace $(MINIKUBE_NAMESPACE) --timeout=30s
200200

201-
deploy-web-ui:
202-
$(KUBECTL) apply -f $(PWD)/minikube/web-ui.yaml --namespace $(MINIKUBE_NAMESPACE)
203-
$(KUBECTL) rollout status deploy/web-ui --namespace $(MINIKUBE_NAMESPACE) --timeout=30s
204201

205202
deploy-mini-application: $(VALUES) $(LOCAL_REST_API_DEPLOY) build-rest-api-mini
206203
$(eval CONFIG_HASH = $(shell md5 -q $(VALUES)))
207204
CONFIG_HASH=$(CONFIG_HASH) $(YQ) e '.podAnnotations.configHash = strenv(CONFIG_HASH)' -i $(VALUES)
208205
$(HELM) template $(REST_API_IMAGE_NAME) $(PWD) \
209206
--dry-run \
210207
--values=$(VALUES) | $(SPLIT_YAML) --outdir $(LOCAL_REST_API_DEPLOY) -
208+
$(KUBECTL) delete svc/$(REST_API_IMAGE_NAME) --namespace $(MINIKUBE_NAMESPACE)
211209
$(KUBECTL) apply -f $(LOCAL_REST_API_DEPLOY) --namespace $(MINIKUBE_NAMESPACE)
212210
$(KUBECTL) rollout status deploy/rest-api --namespace $(MINIKUBE_NAMESPACE) --timeout=30s
213211

@@ -218,7 +216,6 @@ local-dependencies-maybe:
218216
which $(HELM) || make dependencies-helm
219217
which $(SPLIT_YAML) || make dependencies-split-yaml
220218
which $(YQ) || make dependencies-yq
221-
make dependencies-telepresence # We always want to use our version to make sure it'll work properly.
222219

223220
MINIKUBE_VERSION=latest
224221
dependencies-minikube:
@@ -252,25 +249,14 @@ dependencies-yq:
252249
mv $(YQ_DIR)/$(YQ)_$(OS)_$(ARCH) $(LOCAL_BIN)/$(YQ)
253250
rm -rf $(YQ_DIR) || true
254251

255-
TELEPRESENCE_VERSION=0.109
256-
TELEPRESENCE_URL=https://github.com/telepresenceio/telepresence/archive/refs/tags/$(TELEPRESENCE_VERSION).tar.gz
257-
TELEPRESENCE_DIR=$(LOCAL_TMP)/$(TELEPRESENCE)
258-
dependencies-telepresence:
259-
rm -rf $(TELEPRESENCE_DIR).tar.gz || true
260-
rm -rf $(TELEPRESENCE_DIR) || true
261-
mkdir -p $(TELEPRESENCE_DIR)
262-
curl -L -s $(TELEPRESENCE_URL) -o $(TELEPRESENCE_DIR).tar.gz
263-
tar -xzf $(TELEPRESENCE_DIR).tar.gz -C $(TELEPRESENCE_DIR)
264-
PREFIX=$(PWD) $(TELEPRESENCE_DIR)/$(TELEPRESENCE)-$(TELEPRESENCE_VERSION)/install.sh
265-
rm -rf $(TELEPRESENCE_DIR).tar.gz || true
266-
rm -rf $(TELEPRESENCE_DIR) || true
267-
268-
269252
###################### DEBUGGING THE REST API ##################################
270-
debug-api-mini:
271-
tmux \
272-
new-session '$(TELEPRESENCE) --method=inject-tcp --swap-deployment rest-api --expose 4000 --local-cluster' \; \
273-
split-window 'minikube tunnel' \;
253+
LOCAL_IP=$(shell ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $$2 }' | cut -f2 -d: | head -n1)
254+
local-api:
255+
LOCAL_IP=$(LOCAL_IP) $(YQ) e '.subsets[0].addresses[0].ip = strenv(LOCAL_IP)' $(PWD)/minikube/api-endpoint.yaml | $(KUBECTL) apply -f -
256+
$(KUBECTL) get svc/$(REST_API_IMAGE_NAME) -n $(MINIKUBE_NAMESPACE) -o yaml | $(YQ) e 'del(.spec.selector)' - | $(KUBECTL) apply -f -
257+
tmux new-session 'minikube tunnel' || true
258+
$(KUBECTL) delete svc/$(REST_API_IMAGE_NAME) --namespace $(MINIKUBE_NAMESPACE)
259+
$(KUBECTL) apply -f $(LOCAL_REST_API_DEPLOY) --namespace $(MINIKUBE_NAMESPACE)
274260

275261
###################### WORKING ON WEBHOOKS LOCALLY ##################################
276262
webhooks-mini:

README.md

+9-66
Original file line numberDiff line numberDiff line change
@@ -58,76 +58,19 @@ make deploy-mini-application
5858
This will build a new docker image from your current code as well as evaluate any changes made to the `values.local.yaml`
5959
file in your project directory and push those changes to minikube.
6060

61-
If you want to do step debugging you can use a tool called telepresence. The shorthand make target below will spawn a new
62-
tmux session with both `minikube tunnel` and `telepresence` running side by side. This is because on their own I've found
63-
that telepresence does not always tunnel traffic properly. And minikube has no way to send traffic from its cluster to
64-
a local target. This will do both.
61+
If you want to do step debugging there is a shortcut in the makefile to do so. You will need to create a `config.yaml`
62+
file in your project directory with all the same settings you have specified in your `values.local.yaml` for everything
63+
to work properly. Once you have done that you can run the command below:
6564

6665
```bash
67-
make debug-api-mini
66+
make local-api
6867
```
6968

70-
Which will let you run the REST API on your actual computer and serve requests from minikube there. This means you can
71-
run the REST API in GoLand or VSCode and use a step debugger to debug requests. There is a caveat with doing this though;
72-
configuration is primarily provided to the REST API service in Kubernetes via environment variables. So you may need to
73-
make a `config.yaml` file in your project directory and add any configuration options there in order to run the service
74-
properly. More documentation on that file will be added at a later date.
75-
76-
You'll need to install macFUSE and SSHFS from the installer packages here: https://osxfuse.github.io/
77-
78-
79-
You may see an error like the following in the tmux session that is started:
80-
```
81-
T: Warning: kubectl 1.21.0 may not work correctly with cluster version 1.18.15 due to the version discrepancy. See https://kubernetes.io/docs/setup/version-skew-policy/ for more information.
82-
83-
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems, please file an issue!
84-
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force the old behavior, e.g.,
85-
T: env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello
86-
87-
T: Starting proxy with method 'inject-tcp', which has the following limitations: Go programs, static binaries, suid programs, and custom DNS implementations are not supported. For a full list of method limitations see
88-
T: https://telepresence.io/reference/methods.html
89-
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html for details.
90-
T: Starting network proxy to cluster by swapping out Deployment rest-api with a proxy Pod
91-
T: Forwarding remote port 9000 to local port 9000.
92-
T: Forwarding remote port 4000 to local port 4000.
93-
94-
95-
Looks like there's a bug in our code. Sorry about that!
96-
97-
Traceback (most recent call last):
98-
File "/Users/elliotcourant/monetr/rest-api/bin/telepresence/telepresence/cli.py", line 135, in crash_reporting
99-
yield
100-
File "/Users/elliotcourant/monetr/rest-api/bin/telepresence/telepresence/main.py", line 81, in main
101-
user_process = launch(
102-
File "/Users/elliotcourant/monetr/rest-api/bin/telepresence/telepresence/outbound/setup.py", line 64, in launch
103-
return launch_inject(runner_, command, socks_port, env)
104-
File "/Users/elliotcourant/monetr/rest-api/bin/telepresence/telepresence/outbound/local.py", line 120, in launch_inject
105-
torsocks_env = set_up_torsocks(runner, socks_port)
106-
File "/Users/elliotcourant/monetr/rest-api/bin/telepresence/telepresence/outbound/local.py", line 71, in set_up_torsocks
107-
raise RuntimeError("SOCKS network proxying failed to start...")
108-
RuntimeError: SOCKS network proxying failed to start...
109-
110-
111-
Here are the last few lines of the logfile (see /Users/elliotcourant/monetr/rest-api/telepresence.log for the complete logs):
112-
113-
17.8 TEL | [114] exit -11 in 0.05 secs.
114-
17.9 TEL | [115] Running: torsocks python3 -c 'import socket; socket.socket().connect(('"'"'kubernetes.default'"'"', 443))'
115-
17.9 TEL | [115] exit -11 in 0.05 secs.
116-
18.0 TEL | [116] Running: torsocks python3 -c 'import socket; socket.socket().connect(('"'"'kubernetes.default'"'"', 443))'
117-
18.0 TEL | [116] exit -11 in 0.05 secs.
118-
18.2 TEL | [117] Running: torsocks python3 -c 'import socket; socket.socket().connect(('"'"'kubernetes.default'"'"', 443))'
119-
18.2 TEL | [117] exit -11 in 0.05 secs.
120-
18.3 TEL | [118] Running: torsocks python3 -c 'import socket; socket.socket().connect(('"'"'kubernetes.default'"'"', 443))'
121-
18.3 TEL | [118] exit -11 in 0.05 secs.
122-
18.5 TEL | [119] Running: torsocks python3 -c 'import socket; socket.socket().connect(('"'"'kubernetes.default'"'"', 443))'
123-
18.5 TEL | [119] exit -11 in 0.04 secs.
124-
18.5 TEL | END SPAN local.py:42(set_up_torsocks) 15.0s
125-
126-
Would you like to file an issue in our issue tracker? You'll be able to review and edit before anything is posted to the public. We'd really appreciate the help improving our product. [Y/n]:
127-
```
128-
129-
If you do, **do not enter `n` or exit telepresence**. Chances are it actually did work and is tunneling TCP traffic like
130-
we want it to.
69+
This will spawn a new tmux window with a minikube tunnel in it. This is needed for the API to talk to the services it
70+
needs within the minikube cluster.
71+
This will also swap out the target for the API service in kubernetes with an endpoint pointed at your computer and at port
72+
4000. This way you can run a REST API instance locally through something like GoLand or VSCode and step debug API
73+
requests directly.
13174

13275
### Testing Webhooks
13376

minikube/api-endpoint.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v1
2+
kind: Endpoints
3+
metadata:
4+
name: rest-api
5+
subsets:
6+
- addresses:
7+
- ip: 0.0.0.0
8+
ports:
9+
- port: 4000
10+
name: http
11+
protocol: TCP

minikube/web-ui.yaml

-74
This file was deleted.

pkg/internal/cmd/serve.go

+22-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"github.com/getsentry/sentry-go"
66
"github.com/go-pg/pg/v10"
7+
"github.com/kataras/iris/v12"
78
"github.com/monetrapp/rest-api/pkg/application"
89
"github.com/monetrapp/rest-api/pkg/cache"
910
"github.com/monetrapp/rest-api/pkg/config"
@@ -15,6 +16,7 @@ import (
1516
"github.com/spf13/cobra"
1617
"github.com/stripe/stripe-go/v72"
1718
stripe_client "github.com/stripe/stripe-go/v72/client"
19+
"net"
1820
"net/http"
1921
"os"
2022
"time"
@@ -143,6 +145,24 @@ func RunServer() error {
143145
stripeClient,
144146
)...)
145147

146-
// TODO Allow listen port to be changed via config.
147-
return app.Listen(":4000")
148+
unixSocket := false
149+
150+
if unixSocket {
151+
workingDirectory, err := os.Getwd()
152+
if err != nil {
153+
panic(err)
154+
}
155+
listener, err := net.ListenUnix("unix", &net.UnixAddr{
156+
Name: workingDirectory + "/api.sock",
157+
Net: "unix",
158+
})
159+
if err != nil {
160+
panic(err)
161+
}
162+
163+
return app.Run(iris.Listener(listener))
164+
} else {
165+
// TODO Allow listen port to be changed via config.
166+
return app.Listen(":4000")
167+
}
148168
}

0 commit comments

Comments
 (0)