generated from keploy/template
-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: ayush3160 <[email protected]>
- Loading branch information
Showing
14 changed files
with
1,100 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mux-elasticsearch |
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,23 @@ | ||
# Use the Go 1.19 base image with the bullseye tag | ||
FROM golang:1.22-bookworm | ||
|
||
|
||
RUN apt-get update && \ | ||
apt-get install -y --no-install-recommends ca-certificates && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
# Set the working directory inside the container | ||
WORKDIR /app | ||
|
||
COPY go.mod /app/ | ||
COPY go.sum /app/ | ||
|
||
RUN go mod download | ||
|
||
# Copy the contents from the local directory to the working directory in the container | ||
COPY . /app | ||
|
||
RUN go build -o app . | ||
|
||
# Run the application server using "go run handler.go main.go" | ||
CMD ["./app"] |
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,86 @@ | ||
# Introduction | ||
This is a sample go project to show the crud operations of golang with elasticsearch and mux. | ||
|
||
## Installation Setup | ||
|
||
```bash | ||
git clone https://github.com/keploy/samples-go.git && cd samples-go/mux-elasticsearch | ||
go mod download | ||
``` | ||
|
||
## Installation Keploy | ||
Install keploy via one-click:- | ||
|
||
```sh | ||
curl --silent -O -L https://keploy.io/install.sh && source install.sh | ||
``` | ||
|
||
### Install And Run Elastic | ||
|
||
Using the docker we will start our elastic instance:- | ||
|
||
```bash | ||
docker run --name=es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.14.3 | ||
``` | ||
|
||
In the above command we are passing two environment variables to run the elastic in dev mode and disabling the need to pass the password to connect to elastic database. If you want to enable it you can follow steps mentioned on this [page](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html) . Then you have to pass the password and http cert file to connect. | ||
|
||
|
||
### Capture the Testcases | ||
|
||
Now, we will create the binary of our application:- | ||
|
||
```zsh | ||
go build -cover | ||
``` | ||
|
||
Once we have our binary file ready,this command will start the recording of API calls using ebpf:- | ||
|
||
```shell | ||
sudo -E keploy record -c "./mux-elasticsearch" | ||
``` | ||
|
||
Make API Calls using Hoppscotch, Postman or cURL command. Keploy with capture those calls to generate the test-suites containing testcases and data mocks. | ||
|
||
#### Generate testcases | ||
|
||
To genereate testcases we just need to make some API calls. You can use [Postman](https://www.postman.com/), [Hoppscotch](https://hoppscotch.io/), or simply `curl` | ||
|
||
1. Post Command To Insert Document | ||
|
||
```bash | ||
curl --request POST \ | ||
--url http://localhost:8000/documents \ | ||
--header 'Content-Type: application/json' \ | ||
--data '{ | ||
"title" : "somethingTitle", | ||
"content" : "something22" | ||
}' | ||
``` | ||
this will return the response which includes the id of the inserted document. | ||
```json | ||
{"id":"1b5wJ5EBIPW7ZBPsse8e"} | ||
``` | ||
|
||
2. Fetch the Products | ||
```bash | ||
curl --request GET \ | ||
--url http://localhost:8000/documents/1b5wJ5EBIPW7ZBPsse8e | ||
``` | ||
|
||
we will get output: | ||
|
||
```json | ||
{"content":"something22","title":"somethingTitle"} | ||
``` | ||
|
||
|
||
Now let's run the test mode (in the mux-elasticsearch directory, not the Keploy directory). | ||
|
||
### Run captured testcases | ||
|
||
```shell | ||
sudo -E keploy test -c "./mux-elasticsearch" --delay 10 --goCoverage | ||
``` | ||
|
||
|
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,243 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
"os/signal" | ||
"strings" | ||
"time" | ||
|
||
"github.com/elastic/go-elasticsearch/v8" | ||
"github.com/elastic/go-elasticsearch/v8/esapi" | ||
"github.com/gorilla/mux" | ||
) | ||
|
||
type App struct { | ||
Router *mux.Router | ||
DB *elasticsearch.Client | ||
Server *http.Server | ||
} | ||
|
||
const SearchIndex = "documents" | ||
|
||
func (a *App) Initialize() error { | ||
var err error | ||
a.DB, err = elasticsearch.NewDefaultClient() | ||
|
||
if err != nil { | ||
return fmt.Errorf("error : %s", err) | ||
} | ||
|
||
_, err = esapi.IndicesExistsRequest{ | ||
Index: []string{SearchIndex}, | ||
}.Do(context.Background(), a.DB) | ||
|
||
if err != nil { | ||
fmt.Println("Indices is not present") | ||
a.CreateIndices() | ||
} | ||
|
||
a.Router = mux.NewRouter() | ||
a.Server = &http.Server{ | ||
Addr: ":8000", | ||
Handler: a.Router, | ||
} | ||
|
||
a.initializeRoutes() | ||
|
||
return nil | ||
} | ||
|
||
type Document struct { | ||
ID string `json:"id,omitempty"` | ||
Title string `json:"title"` | ||
Content string `json:"content"` | ||
} | ||
|
||
type CreateDocumentResponse struct { | ||
ID string `json:"_id"` | ||
} | ||
|
||
func (a *App) CreateIndices() { | ||
var err error | ||
|
||
_, err = a.DB.Indices.Create(SearchIndex) | ||
|
||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
} | ||
|
||
func (a *App) createDocument(w http.ResponseWriter, r *http.Request) { | ||
var doc Document | ||
err := json.NewDecoder(r.Body).Decode(&doc) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
|
||
data, err := json.Marshal(doc) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
req := esapi.IndexRequest{ | ||
Index: "documents", | ||
Body: strings.NewReader(string(data)), | ||
} | ||
res, err := req.Do(context.Background(), a.DB) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
defer res.Body.Close() | ||
|
||
if res.IsError() { | ||
http.Error(w, res.String(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
var createResponse CreateDocumentResponse | ||
if err := json.NewDecoder(res.Body).Decode(&createResponse); err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusCreated) | ||
json.NewEncoder(w).Encode(map[string]string{"id": createResponse.ID}) | ||
} | ||
|
||
func (a *App) getDocument(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id := params["id"] | ||
|
||
req := esapi.GetRequest{ | ||
Index: "documents", | ||
DocumentID: id, | ||
} | ||
res, err := req.Do(context.Background(), a.DB) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
defer res.Body.Close() | ||
|
||
if res.IsError() { | ||
http.Error(w, res.String(), http.StatusNotFound) | ||
return | ||
} | ||
|
||
var doc map[string]interface{} | ||
if err := json.NewDecoder(res.Body).Decode(&doc); err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
source := doc["_source"].(map[string]interface{}) | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
json.NewEncoder(w).Encode(source) | ||
} | ||
|
||
func (a *App) updateDocument(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id := params["id"] | ||
|
||
var doc Document | ||
err := json.NewDecoder(r.Body).Decode(&doc) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
|
||
data, err := json.Marshal(doc) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
req := esapi.UpdateRequest{ | ||
Index: "documents", | ||
DocumentID: id, | ||
Body: strings.NewReader(fmt.Sprintf(`{"doc": %s}`, string(data))), | ||
} | ||
res, err := req.Do(context.Background(), a.DB) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
defer res.Body.Close() | ||
|
||
if res.IsError() { | ||
http.Error(w, res.String(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
func (a *App) deleteDocument(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id := params["id"] | ||
|
||
req := esapi.DeleteRequest{ | ||
Index: "documents", | ||
DocumentID: id, | ||
} | ||
res, err := req.Do(context.Background(), a.DB) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
defer res.Body.Close() | ||
|
||
if res.IsError() { | ||
http.Error(w, res.String(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
func (a *App) Run(port string) { | ||
go func() { | ||
if err := a.Server.ListenAndServe(); err != nil && err != http.ErrServerClosed { | ||
log.Fatalf("Could not listen on %s: %v\n", port, err) | ||
} | ||
}() | ||
|
||
quit := make(chan os.Signal, 1) | ||
signal.Notify(quit, os.Interrupt) | ||
<-quit | ||
|
||
log.Println("Server is shutting down...") | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | ||
defer cancel() | ||
|
||
if err := a.Server.Shutdown(ctx); err != nil { | ||
log.Fatalf("Server forced to shutdown: %v", err) | ||
} | ||
|
||
log.Println("Server exiting") | ||
} | ||
|
||
func (a *App) Hello(res http.ResponseWriter, req *http.Request) { | ||
var result = "Hello" | ||
res.Write([]byte(result)) | ||
} | ||
|
||
func (a *App) initializeRoutes() { | ||
a.Router.HandleFunc("/", a.Hello).Methods("GET") | ||
a.Router.HandleFunc("/documents", a.createDocument).Methods("POST") | ||
a.Router.HandleFunc("/documents/{id}", a.getDocument).Methods("GET") | ||
a.Router.HandleFunc("/documents/{id}", a.updateDocument).Methods("PUT") | ||
a.Router.HandleFunc("/documents/{id}", a.deleteDocument).Methods("DELETE") | ||
|
||
} |
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 @@ | ||
module mux-elasticsearch | ||
|
||
go 1.22 | ||
|
||
require ( | ||
github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect | ||
github.com/elastic/go-elasticsearch/v8 v8.14.0 // indirect | ||
github.com/go-logr/logr v1.4.1 // indirect | ||
github.com/go-logr/stdr v1.2.2 // indirect | ||
github.com/gorilla/mux v1.8.1 // indirect | ||
go.opentelemetry.io/otel v1.24.0 // indirect | ||
go.opentelemetry.io/otel/metric v1.24.0 // indirect | ||
go.opentelemetry.io/otel/trace v1.24.0 // indirect | ||
) |
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,17 @@ | ||
github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHoSjSRSJCApolgfthA= | ||
github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= | ||
github.com/elastic/go-elasticsearch/v8 v8.14.0 h1:1ywU8WFReLLcxE1WJqii3hTtbPUE2hc38ZK/j4mMFow= | ||
github.com/elastic/go-elasticsearch/v8 v8.14.0/go.mod h1:WRvnlGkSuZyp83M2U8El/LGXpCjYLrvlkSgkAH4O5I4= | ||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= | ||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= | ||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= | ||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= | ||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= | ||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= | ||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= | ||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= | ||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= | ||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= | ||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= | ||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= |
Oops, something went wrong.