Skip to content

Commit

Permalink
Merge pull request #135 from Kong/api-summit-24
Browse files Browse the repository at this point in the history
WIP: Adding ephemeral test env for routes team. Summit demo
  • Loading branch information
rspurgeon authored Aug 20, 2024
2 parents 8bf59f2 + ac64cac commit 9e4e7e5
Show file tree
Hide file tree
Showing 14 changed files with 357 additions and 32 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ kong-quickstart.*
kong.env
kong.yaml
*.pid
tls*/
*.env
*.log
2 changes: 2 additions & 0 deletions base.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ PORTS_FILE := $(BASE_MAKEFILE_DIR)PORTS.env

echo_fail = printf "\e[31m✘ \033\e[0m$(1)\n"
echo_pass = printf "\e[32m✔ \033\e[0m$(1)\n"
echo_info = printf "\e[33mℹ \033\e[0m$(1)\n"
echo_bull = printf "\e[34m• \033\e[0m$1\n"

check-dependency = $(if $(shell command -v $(1)),$(call echo_pass,found $(1)),$(call echo_fail,$(1) not installed);exit 1)

Expand Down
2 changes: 2 additions & 0 deletions flight-data/routes/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
routes

tls.*
4 changes: 2 additions & 2 deletions flight-data/routes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ RUN CGO_ENABLED=0 go build -o /go/bin/app
FROM gcr.io/distroless/static-debian11

COPY --from=build /go/bin/app /
EXPOSE 8080
CMD ["/app"]
EXPOSE 8081
CMD ["/app", "8081"]
117 changes: 114 additions & 3 deletions flight-data/routes/Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,124 @@
include ../../base.mk

routes_mkfile_dir := $(CURRDIR)

check-dependencies:
@$(call check-dependency,go)
@$(call check-dependency,jq)
@$(call check-dependency,deck)
@$(call check-dependency,cloudflared)
@$(call check-dependency,docker)

test: check-dependencies
go test -v ./...
@go test -v ./...

build: check-dependencies
go build .
@go build .

build-docker:
@docker build -t kong-air-routes-svc:dev .

run: check-dependencies build
./routes ${KONG_AIR_ROUTES_PORT}
@./routes ${KONG_AIR_ROUTES_PORT}

docker: build-docker
@docker run -d --name kong-air-routes-svc -p ${KONG_AIR_ROUTES_PORT}:${KONG_AIR_ROUTES_PORT} kong-air-routes-svc:dev

kill-docker:
-@docker stop kong-air-routes-svc
-@docker rm kong-air-routes-svc
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to kill the docker containers); exit 1; else $(call echo_pass,Killed the docker container); fi

###############################################################################
# DEV Environment setup
TLS_KEY := $(CURDIR)/dev/kong/konnect/tf/tls.key
TLS_CRT := $(CURDIR)/dev/kong/konnect/tf/tls.crt
TF_OUT_LOG := $(CURDIR)/dev/kong/konnect/tf/.terraform.out.log
TF_ERR_LOG := $(CURDIR)/dev/kong/konnect/tf/.terraform.err.log

$(TLS_KEY) $(TLS_CRT):
@openssl req -new -x509 -nodes -newkey rsa:2048 -subj "/CN=kongdp/C=US" -keyout $(TLS_KEY) -out $(TLS_CRT) > /dev/null 2>&1

konnect-dev-cert: $(TLS_KEY) $(TLS_CRT)
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to create Konnect certificate); exit 1; else $(call echo_pass,Created Konnect certificate); fi

kill-konnect-dev-cert:
@rm -f $(TLS_KEY) $(TLS_CRT)
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to remove Konnect certificate); exit 1; else $(call echo_pass,Removed Konnect certificate); fi

konnect-dev-tf-init:
@cd $(CURDIR)/dev/kong/konnect/tf && terraform init > $(TF_OUT_LOG) 2> $(TF_ERR_LOG)
@if [ $$? -ne 0 ]; then $(call echo_fail,terraform failed to initialize); exit 1; else $(call echo_pass,terraform initialized); fi

konnect-dev-tf-apply:
@cd $(CURDIR)/dev/kong/konnect/tf && KONNECT_TOKEN=`cat ~/.konnect/routes-dev.pat` terraform apply -auto-approve > $(TF_OUT_LOG) 2> $(TF_ERR_LOG) && \
echo "KONG_GATEWAY_URL=$$(terraform output -json | jq -r .gateway_endpoint.value)" > $(CURDIR)/dev/kong/konnect/.kong-air-routes-svc.env && \
echo "KONNECT_CONTROL_PLANE_NAME=$$(terraform output -json | jq -r .control_plane_name.value)" >> $(CURDIR)/dev/kong/konnect/.kong-air-routes-svc.env
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to apply terraform manifests); exit 1; else $(call echo_pass,Konnect resources available); fi

konnect-dev-tf-destroy:
@cd $(CURDIR)/dev/kong/konnect/tf && KONNECT_TOKEN=`cat ~/.konnect/routes-dev.pat` terraform destroy -auto-approve > $(TF_OUT_LOG) 2> $(TF_ERR_LOG)
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to destroy terraform resources); exit 1; else $(call echo_pass,Destroyed Konnect resources); fi

konnect-dev-env: konnect-dev-cert konnect-dev-tf-init konnect-dev-tf-apply

kill-konnect-dev-env: konnect-dev-tf-destroy kill-konnect-dev-cert

cloudflare-tunnel:
@cloudflared tunnel run routes > ~/Library/Logs/com.cloudflare.cloudflared.out.log 2> ~/Library/Logs/com.cloudflare.cloudflared.err.log & \
echo $$! > $(CURDIR)/.cloudflared.pid
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to run cloudflare tunnel); exit 1; \
else $(call echo_pass,cloudflare tunnel running at PID $$(cat $(CURDIR)/.cloudflared.pid)); fi

kill-cloudflare-tunnel:
@if [ -f $(CURDIR)/.cloudflared.pid ]; then \
kill $$(cat $(CURDIR)/.cloudflared.pid) || true; \
rm $(CURDIR)/.cloudflared.pid; \
$(call echo_pass,Killed the cloudflare tunnel); \
fi

routes-svc-kong-config:
@deck file openapi2kong -s openapi.yaml | \
deck file patch --output-file $(CURDIR)/dev/kong/.kong-routes-svc.yaml $(CURDIR)/dev/kong/patches.yaml
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to create Kong configuration); exit 1; \
else $(call echo_pass,Wrote Kong configuration to dev/kong/.kong-routes-svc.yaml); fi

kill-route-svc-kong-config:
@rm -f $(CURDIR)/dev/kong/.kong-routes-svc.yaml

sync-routes-svc-kong-config:
@source $(CURDIR)/dev/kong/konnect/.kong-air-routes-svc.env && \
deck gateway sync \
--konnect-token-file ~/.konnect/routes-dev.pat \
--konnect-control-plane-name $$KONNECT_CONTROL_PLANE_NAME \
$(CURDIR)/dev/kong/.kong-routes-svc.yaml
@if [ $$? -ne 0 ]; then $(call echo_fail,Failed to sync Kong configuration); exit 1; \
else $(call echo_pass,Synced Kong configuration); fi

.PHONY: dev-env
dev-env: check-dependencies
@$(call echo_bull,Creating a kong-air routes team dev environment)
@$(MAKE) docker
@$(MAKE) konnect-dev-env
@$(MAKE) cloudflare-tunnel
@$(MAKE) routes-svc-kong-config
@$(MAKE) sync-routes-svc-kong-config
@echo
@echo "Run the following command to load the dev environment variables"
@echo "source dev/kong/konnect/.kong-air-routes-svc.env"
@echo
@echo "The Kong Gateway proxy endpoint is available in the variable KONG_GATEWAY_URL"
@echo "Route a request to Kong Gateway with:"
@echo " curl `source $(CURDIR)/dev/kong/konnect/.kong-air-routes-svc.env && echo $$KONG_GATEWAY_URL`"
@echo
@echo "You can also route directly to your service from the Cloudflare public endpoint:"
@echo " curl https://routes.kong-air.dev/routes"

.PHONY: kill-dev-env
kill-dev-env: check-dependencies
@$(MAKE) kill-route-svc-kong-config
@$(MAKE) kill-cloudflare-tunnel
@$(MAKE) kill-konnect-dev-env
@$(MAKE) kill-docker
@echo "Killed the dev environment"
###############################################################################
67 changes: 40 additions & 27 deletions flight-data/routes/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,63 @@ package api
import (
"github.com/Kong/KongAir/flight-data/routes/api/models"
"github.com/labstack/echo/v4"
"net/http"
"net/http"
)

type RouteService struct {
Routes []models.Route
Routes []models.Route
PrivateRoutes []models.Route
}

func NewRouteService() *RouteService {
rv := RouteService{}
rv.Routes = []models.Route{
{Id: "LHR-JFK", Origin: "LHR", Destination: "JFK", AvgDuration: 470},
{Id: "LHR-SFO", Origin: "LHR", Destination: "SFO", AvgDuration: 660},
{Id: "LHR-DXB", Origin: "LHR", Destination: "DXB", AvgDuration: 420},
{Id: "LHR-HKG", Origin: "LHR", Destination: "HKG", AvgDuration: 745},
{Id: "LHR-BOM", Origin: "LHR", Destination: "BOM", AvgDuration: 540},
{Id: "LHR-HND", Origin: "LHR", Destination: "HND", AvgDuration: 830},
{Id: "LHR-CPT", Origin: "LHR", Destination: "CPT", AvgDuration: 700},
{Id: "LHR-SYD", Origin: "LHR", Destination: "SYD", AvgDuration: 1320},
{Id: "LHR-SIN", Origin: "LHR", Destination: "SIN", AvgDuration: 800},
{Id: "LHR-LAX", Origin: "LHR", Destination: "LAX", AvgDuration: 675},
{Id: "LHR-JFK", Origin: "LHR", Destination: "JFK", AvgDuration: 470},
{Id: "LHR-SFO", Origin: "LHR", Destination: "SFO", AvgDuration: 660},
{Id: "LHR-DXB", Origin: "LHR", Destination: "DXB", AvgDuration: 420},
{Id: "LHR-HKG", Origin: "LHR", Destination: "HKG", AvgDuration: 745},
{Id: "LHR-BOM", Origin: "LHR", Destination: "BOM", AvgDuration: 540},
{Id: "LHR-HND", Origin: "LHR", Destination: "HND", AvgDuration: 830},
{Id: "LHR-CPT", Origin: "LHR", Destination: "CPT", AvgDuration: 700},
{Id: "LHR-SYD", Origin: "LHR", Destination: "SYD", AvgDuration: 1320},
{Id: "LHR-SIN", Origin: "LHR", Destination: "SIN", AvgDuration: 800},
{Id: "LHR-LAX", Origin: "LHR", Destination: "LAX", AvgDuration: 675},
}
rv.PrivateRoutes = []models.Route{
{Id: "VIP-LHR-JFK", Origin: "LHR", Destination: "VIP-JFK", AvgDuration: 430},
{Id: "VIP-LHR-SFO", Origin: "LHR", Destination: "VIP-SFO", AvgDuration: 620},
{Id: "VIP-LHR-DXB", Origin: "LHR", Destination: "VIP-DXB", AvgDuration: 390},
{Id: "VIP-LHR-HKG", Origin: "LHR", Destination: "VIP-HKG", AvgDuration: 645},
}
return &rv
}

func (s *RouteService) GetHealth(ctx echo.Context) error {
return ctx.JSON(http.StatusOK, map[string]string{"status": "OK"})
return ctx.JSON(http.StatusOK, map[string]string{"status": "OK"})
}

func (s *RouteService) GetRoutes(ctx echo.Context, params models.GetRoutesParams) error {
err := ctx.JSON(200, s.Routes)
if err != nil {
return err
if ctx.Request().Header.Get("x-vip") == "true" {
allRoutes := append(s.Routes, s.PrivateRoutes...)
return ctx.JSON(200, allRoutes)
}
return nil

return ctx.JSON(200, s.Routes)
}

func (s *RouteService) GetRoute(ctx echo.Context, id string) error {
for _, route := range s.Routes {
if route.Id == id {
err := ctx.JSON(200, route)
if err != nil {
return err
}
return nil
}
}
return ctx.JSON(404, nil)
routes := s.Routes
if ctx.Request().Header.Get("x-vip") == "true" {
routes = append(routes, s.PrivateRoutes...)
}
for _, route := range routes {
if route.Id == id {
err := ctx.JSON(200, route)
if err != nil {
return err
}
return nil
}
}
return ctx.JSON(404, nil)
}
1 change: 1 addition & 0 deletions flight-data/routes/dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.kong-routes-svc.yaml
29 changes: 29 additions & 0 deletions flight-data/routes/dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

# Steps

## Initialize Konnect Resources
1. `terraform init`
1. `openssl req -new -x509 -nodes -newkey rsa:2048 -subj "/CN=kongdp/C=US" -keyout ./tls.key -out ./tls.crt`
1. `KONNECT_TOKEN=$(cat ~/.konnect/routes-dev.pat ) terraform apply -auto-approve`

## Run the application
1. `make run`

## Run the cloudflared tunnel

Requires some initial setup including an authenticated cloudflared installation and local configuration. See
https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/

1. cloudflared tunnel login
1. cloudflared tunnel create routes
1. cloudflared tunnel route dns 55f23fbd-9104-4b47-a14b-d068f9b980aa routes
1. Setup a configuration file: `~/.cloudflared/config.yml`

```yaml
url: http://localhost:8081
tunnel: 55f23fbd-9104-4b47-a14b-d068f9b980aa
credentials-file: $HOME/.cloudflared/55f23fbd-9104-4b47-a14b-d068f9b980aa.json
```
## Run the tunnel
1. `cloudflared tunnel run routes`
37 changes: 37 additions & 0 deletions flight-data/routes/dev/kong/konnect/tf/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore transient lock info files created by terraform apply
.terraform.tfstate.lock.info

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc
36 changes: 36 additions & 0 deletions flight-data/routes/dev/kong/konnect/tf/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions flight-data/routes/dev/kong/konnect/tf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


12 changes: 12 additions & 0 deletions flight-data/routes/dev/kong/konnect/tf/konnect.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
required_providers {
konnect = {
source = "kong/konnect"
version = "0.6.0"
}
}
}

provider "konnect" {
server_url = "https://us.api.konghq.com"
}
Loading

0 comments on commit 9e4e7e5

Please sign in to comment.