Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Add demo book app watcher for terminal and raw JSON from web API #3930

Merged
merged 4 commits into from
Aug 9, 2021
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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ $(DEMO_BUILD_TARGETS):
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ./demo/bin/$(NAME)/$(NAME) ./demo/cmd/$(NAME)
@if [ -f demo/$(NAME).html.template ]; then cp demo/$(NAME).html.template demo/bin/$(NAME); fi

.PHONE: build-bookwatcher
build-bookwatcher:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ./demo/bin/bookwatcher/bookwatcher ./demo/cmd/bookwatcher

.PHONY: demo-build
demo-build: $(DEMO_BUILD_TARGETS) build-init-osm-controller build-osm-controller build-osm-injector build-osm-crds build-osm-crd-converter

Expand Down
27 changes: 16 additions & 11 deletions demo/cmd/bookbuyer/bookbuyer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ const (
)

var (
books common.BookBuyerPurchases
wg sync.WaitGroup
booksBought int64
booksBoughtV1 int64
booksBoughtV2 int64
log = logger.NewPretty(participantName)
port = flag.Int("port", 14001, "port on which this app is listening for incoming HTTP")
path = flag.String("path", ".", "path to the HTML template")
Expand All @@ -50,9 +48,9 @@ func renderTemplate(w http.ResponseWriter) {
}
err = tmpl.Execute(w, map[string]string{
"Identity": getIdentity(),
"BooksBoughtV1": fmt.Sprintf("%d", booksBoughtV1),
"BooksBoughtV2": fmt.Sprintf("%d", booksBoughtV2),
"BooksBought": fmt.Sprintf("%d", booksBought),
"BooksBoughtV1": fmt.Sprintf("%d", books.BooksBoughtV1),
"BooksBoughtV2": fmt.Sprintf("%d", books.BooksBoughtV2),
"BooksBought": fmt.Sprintf("%d", books.BooksBought),
"Time": time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST"),
})
if err != nil {
Expand All @@ -62,7 +60,7 @@ func renderTemplate(w http.ResponseWriter) {

func getIndex(w http.ResponseWriter, r *http.Request) {
renderTemplate(w)
fmt.Printf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), booksBought)
fmt.Printf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), books.BooksBought)
}

func debugServer() {
Expand All @@ -81,22 +79,29 @@ func debugServer() {
func getHandlers() []handler {
return []handler{
{"/", getIndex, "GET"},
{"/raw", common.GetRawGenerator(&books), "GET"},
{"/reset", reset, "GET"},
}
}

func reset(w http.ResponseWriter, _ *http.Request) {
atomic.StoreInt64(&booksBought, 0)
atomic.StoreInt64(&booksBoughtV1, 0)
atomic.StoreInt64(&booksBoughtV2, 0)
atomic.StoreInt64(&books.BooksBought, 0)
atomic.StoreInt64(&books.BooksBoughtV1, 0)
atomic.StoreInt64(&books.BooksBoughtV2, 0)
renderTemplate(w)
}

func getBooksWrapper(wg *sync.WaitGroup) {
defer wg.Done()

meshExpectedResponseCode := http.StatusOK
common.GetBooks(participantName, meshExpectedResponseCode, &booksBought, &booksBoughtV1, &booksBoughtV2)
common.GetBooks(
participantName,
meshExpectedResponseCode,
&books.BooksBought,
&books.BooksBoughtV1,
&books.BooksBoughtV2,
)
}

func main() {
Expand Down
29 changes: 15 additions & 14 deletions demo/cmd/bookstore/bookstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import (
)

var (
booksSold int64 = 0
log = logger.NewPretty("bookstore")
identity = flag.String("ident", "unidentified", "the identity of the container where this demo app is running (VM, K8s, etc)")
port = flag.Int("port", 14001, "port on which this app is listening for incoming HTTP")
path = flag.String("path", ".", "path to the HTML template")
books common.BookStorePurchases
log = logger.NewPretty("bookstore")
identity = flag.String("ident", "unidentified", "the identity of the container where this demo app is running (VM, K8s, etc)")
port = flag.Int("port", 14001, "port on which this app is listening for incoming HTTP")
path = flag.String("path", ".", "path to the HTML template")
)

type handler struct {
Expand All @@ -44,7 +44,7 @@ func getIdentity() string {
}

func setHeaders(w http.ResponseWriter, r *http.Request) {
w.Header().Set(common.BooksBoughtHeader, fmt.Sprintf("%d", booksSold))
w.Header().Set(common.BooksBoughtHeader, fmt.Sprintf("%d", books.BooksSold))
w.Header().Set(common.IdentityHeader, getIdentity())

if r != nil {
Expand All @@ -63,7 +63,7 @@ func renderTemplate(w http.ResponseWriter) {
}
err = tmpl.Execute(w, map[string]string{
"Identity": getIdentity(),
"BooksSold": fmt.Sprintf("%d", booksSold),
"BooksSold": fmt.Sprintf("%d", books.BooksSold),
"Time": time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST"),
})
if err != nil {
Expand All @@ -74,13 +74,13 @@ func renderTemplate(w http.ResponseWriter) {
func getBooksSold(w http.ResponseWriter, r *http.Request) {
setHeaders(w, r)
renderTemplate(w)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), booksSold)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), books.BooksSold)
}

func getIndex(w http.ResponseWriter, r *http.Request) {
setHeaders(w, r)
renderTemplate(w)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), booksSold)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), books.BooksSold)
}

// updateBooksSold updates the booksSold value to the one specified by the user
Expand All @@ -90,19 +90,19 @@ func updateBooksSold(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Fatal().Err(err).Msg("Could not decode request body")
}
atomic.StoreInt64(&booksSold, updatedBooksSold)
atomic.StoreInt64(&books.BooksSold, updatedBooksSold)
setHeaders(w, r)
renderTemplate(w)
log.Info().Msgf("%s; URL: %q; %s: %d\n", getIdentity(), html.EscapeString(r.URL.Path), common.BooksBoughtHeader, booksSold)
log.Info().Msgf("%s; URL: %q; %s: %d\n", getIdentity(), html.EscapeString(r.URL.Path), common.BooksBoughtHeader, books.BooksSold)
}

// sellBook increments the value of the booksSold
func sellBook(w http.ResponseWriter, r *http.Request) {
fmt.Println("Selling a book!")
atomic.AddInt64(&booksSold, 1)
atomic.AddInt64(&books.BooksSold, 1)
setHeaders(w, r)
renderTemplate(w)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), booksSold)
log.Info().Msgf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), books.BooksSold)
// Loop through headers
for name, headers := range r.Header {
name = strings.ToLower(name)
Expand Down Expand Up @@ -130,13 +130,14 @@ func getHandlers() []handler {
{"/buy-a-book/new", sellBook, "GET"},
{"/reset", reset, "GET"},
{"/liveness", ok, "GET"},
{"/raw", common.GetRawGenerator(&books), "GET"},
{"/readiness", ok, "GET"},
{"/startup", ok, "GET"},
}
}

func reset(w http.ResponseWriter, _ *http.Request) {
booksSold = 0
books.BooksSold = 0
renderTemplate(w)
}

Expand Down
33 changes: 19 additions & 14 deletions demo/cmd/bookthief/bookthief.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ const (
)

var (
booksStolen int64
booksStolenV1 int64
booksStolenV2 int64
log = logger.NewPretty(participantName)
port = flag.Int("port", 14001, "port on which this app is listening for incoming HTTP")
path = flag.String("path", ".", "path to the HTML template")
books common.BookThiefThievery
log = logger.NewPretty(participantName)
port = flag.Int("port", 14001, "port on which this app is listening for incoming HTTP")
path = flag.String("path", ".", "path to the HTML template")
)

func renderTemplate(w http.ResponseWriter) {
Expand All @@ -36,9 +34,9 @@ func renderTemplate(w http.ResponseWriter) {
}
err = tmpl.Execute(w, map[string]string{
"Identity": getIdentity(),
"BooksStolenV1": fmt.Sprintf("%d", booksStolenV1),
"BooksStolenV2": fmt.Sprintf("%d", booksStolenV2),
"BooksStolen": fmt.Sprintf("%d", booksStolen),
"BooksStolenV1": fmt.Sprintf("%d", books.BooksStolenV1),
"BooksStolenV2": fmt.Sprintf("%d", books.BooksStolenV2),
"BooksStolen": fmt.Sprintf("%d", books.BooksStolen),
"Time": time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST"),
})
if err != nil {
Expand All @@ -57,20 +55,21 @@ type handler struct {

func getIndex(w http.ResponseWriter, r *http.Request) {
renderTemplate(w)
fmt.Printf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), booksStolen)
fmt.Printf("%s; URL: %q; Count: %d\n", getIdentity(), html.EscapeString(r.URL.Path), books.BooksStolen)
}

func getHandlers() []handler {
return []handler{
{"/", getIndex, "GET"},
{"/raw", common.GetRawGenerator(&books), "GET"},
{"/reset", reset, "GET"},
}
}

func reset(w http.ResponseWriter, _ *http.Request) {
booksStolen = 0
booksStolenV1 = 0
booksStolenV2 = 0
books.BooksStolen = 0
books.BooksStolenV1 = 0
books.BooksStolenV2 = 0
renderTemplate(w)
}
func debugServer() {
Expand Down Expand Up @@ -100,5 +99,11 @@ func main() {
//
// When it tries to make an egress request, we expect a 200 response with egress enabled and a 404 response with egress disabled.
meshExpectedResponseCode := common.GetExpectedResponseCodeFromEnvVar(common.BookthiefExpectedResponseCodeEnvVar, httpStatusNotFound)
common.GetBooks(participantName, meshExpectedResponseCode, &booksStolen, &booksStolenV1, &booksStolenV2)
common.GetBooks(
participantName,
meshExpectedResponseCode,
&books.BooksStolen,
&books.BooksStolenV1,
&books.BooksStolenV2,
)
}
152 changes: 152 additions & 0 deletions demo/cmd/bookwatcher/bookwatcher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
"time"

"github.com/openservicemesh/osm/demo/cmd/common"
)

const (
bookBuyerPort = 8080
bookStoreV1Port = 8081
bookStoreV2Port = 8082
bookThiefPort = 8083
)

func clearScreen() {
fmt.Print("\033[H\033[2J")
}

func printGreenln(msg string) {
fmt.Printf("\033[32m%s\033[0m\n", msg)
}

func printYellowln(msg string) {
fmt.Printf("\033[33m%s\033[0m\n", msg)
}

func printRedln(msg string) {
fmt.Printf("\033[31m%s\033[0m\n", msg)
}

func getBookData(dest interface{}, port int, wg *sync.WaitGroup, errc chan<- error) {
defer wg.Done()

resp, err := http.Get(fmt.Sprintf("http://localhost:%d/raw", port))
if err != nil {
errc <- fmt.Errorf("error fetching data (port %d): %v", port, err)
return
}
defer func() {
if err := resp.Body.Close(); err != nil {
errc <- fmt.Errorf("error closing response (port %d): %v", port, err)
}
}()

output, err := ioutil.ReadAll(resp.Body)
if err != nil {
errc <- fmt.Errorf("error reading data (port %d): %v", port, err)
return
}

err = json.Unmarshal(output, dest)
if err != nil {
errc <- fmt.Errorf("error unmarshalling data (port %d): %v", port, err)
}
}

func main() {
bookBuyerPurchases := &common.BookBuyerPurchases{}
bookThiefThievery := &common.BookThiefThievery{}
bookStorePurchasesV1 := &common.BookStorePurchases{}
bookStorePurchasesV2 := &common.BookStorePurchases{}
wg := &sync.WaitGroup{}
errc := make(chan error, 4)

for {
clearScreen()

bookBuyerPurchasesTemp := *bookBuyerPurchases
wg.Add(1)
go getBookData(bookBuyerPurchases, bookBuyerPort, wg, errc)

bookThiefThieveryTemp := *bookThiefThievery
wg.Add(1)
go getBookData(bookThiefThievery, bookThiefPort, wg, errc)

bookStorePurchasesV1Temp := *bookStorePurchasesV1
wg.Add(1)
go getBookData(bookStorePurchasesV1, bookStoreV1Port, wg, errc)

bookStorePurchasesV2Temp := *bookStorePurchasesV2
wg.Add(1)
go getBookData(bookStorePurchasesV2, bookStoreV2Port, wg, errc)

complete := make(chan bool)
go func() {
wg.Wait()
close(complete)
}()

select {
case err := <-errc:
wg.Wait()
close(errc)
log.Fatal(err)
case <-complete:
}

bookBuyerHasChanged := bookBuyerPurchases.BooksBought-bookBuyerPurchasesTemp.BooksBought != 0 ||
bookBuyerPurchases.BooksBoughtV1-bookBuyerPurchasesTemp.BooksBoughtV1 != 0 ||
bookBuyerPurchases.BooksBoughtV2-bookBuyerPurchasesTemp.BooksBoughtV2 != 0

bookThiefHasChanged := bookThiefThievery.BooksStolen-bookThiefThieveryTemp.BooksStolen != 0 ||
bookThiefThievery.BooksStolenV1-bookThiefThieveryTemp.BooksStolenV1 != 0 ||
bookThiefThievery.BooksStolenV2-bookThiefThieveryTemp.BooksStolenV2 != 0

bookStoreV1HasChanged := bookStorePurchasesV1.BooksSold-bookStorePurchasesV1Temp.BooksSold != 0
bookStoreV2HasChanged := bookStorePurchasesV2.BooksSold-bookStorePurchasesV2Temp.BooksSold != 0

printFunc := printYellowln
if bookBuyerHasChanged {
printFunc = printGreenln
}
printFunc(fmt.Sprintf(
"bookbuyer Books bought: %d V1 books bought: %d V2 books bought: %d",
bookBuyerPurchases.BooksBought,
bookBuyerPurchases.BooksBoughtV1,
bookBuyerPurchases.BooksBoughtV2,
))

printFunc = printYellowln
if bookThiefHasChanged {
printFunc = printRedln
}
printFunc(fmt.Sprintf(
"bookthief Books stolen: %d V1 books stolen: %d V2 books stolen: %d",
bookThiefThievery.BooksStolen,
bookThiefThievery.BooksStolenV1,
bookThiefThievery.BooksStolenV2,
))

printFunc = printYellowln
if bookStoreV1HasChanged {
printFunc = printGreenln
}
printFunc(fmt.Sprintf("bookstore v1 Books sold: %d", bookStorePurchasesV1.BooksSold))

printFunc = printYellowln
if bookStoreV2HasChanged {
printFunc = printGreenln
}
printFunc(fmt.Sprintf("bookstore v2 Books sold: %d", bookStorePurchasesV2.BooksSold))

time.Sleep(1 * time.Second)
}
}
Loading