-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2612 from CrowleyRajapakse/wso2-apk-code-challenge
Adding apk code challenge artifacts
- Loading branch information
Showing
7 changed files
with
373 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,56 @@ | ||
# WSO2 APK Code Challenge ToDo Service | ||
|
||
## Docker Image | ||
|
||
docker pull sampathrajapakse/todo-service:latest | ||
|
||
## Docker Image Creation | ||
|
||
Use the above provided docker image or you can build using following commands. | ||
|
||
docker buildx create --use | ||
|
||
docker buildx inspect --bootstrap | ||
|
||
docker buildx build --platform linux/amd64,linux/arm64 -t sampathrajapakse/todo-service:latest --push . | ||
|
||
## Deploy in K8s Cluster | ||
|
||
kubectl create ns apk | ||
|
||
kubectl apply -f k8s-artifacts/deployment.yaml -n apk | ||
|
||
## Access the pod locally | ||
|
||
kubectl port-forward pod/todo-app-<random-id> 8080:8080 -n apk | ||
|
||
## Invoke the services | ||
|
||
### Retrieve all to-dos | ||
|
||
curl http://localhost:8080/todos | ||
|
||
### Create a new to-do | ||
|
||
curl -X POST http://localhost:8080/todos \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"task": "Buy groceries", "done": false}' | ||
|
||
### Retrieve a single to-do | ||
|
||
curl http://localhost:8080/todos/1 | ||
|
||
### Update an existing to-do | ||
|
||
curl -X PUT http://localhost:8080/todos/1 \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"task": "Buy groceries", "done": true}' | ||
|
||
### Delete a to-do | ||
|
||
curl -X DELETE http://localhost:8080/todos/1 | ||
|
||
### Register a user with user-reg header | ||
|
||
curl -X POST http://localhost:8080/register \ | ||
-H "user-reg: sampath" |
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,41 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: todo-app | ||
labels: | ||
app: todo-app | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: todo-app | ||
template: | ||
metadata: | ||
labels: | ||
app: todo-app | ||
spec: | ||
containers: | ||
- name: todo-app | ||
image: sampathrajapakse/todo-service:latest | ||
ports: | ||
- containerPort: 8080 | ||
resources: | ||
limits: | ||
memory: "128Mi" | ||
cpu: "500m" | ||
requests: | ||
memory: "64Mi" | ||
cpu: "250m" | ||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: todo-app-service | ||
spec: | ||
selector: | ||
app: todo-app | ||
ports: | ||
- protocol: TCP | ||
port: 80 | ||
targetPort: 8080 | ||
type: LoadBalancer |
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,144 @@ | ||
openapi: 3.0.3 | ||
info: | ||
title: To-Do API | ||
description: A simple to-do service API | ||
version: 1.0.0 | ||
servers: | ||
- url: http://todo-app-service:80 | ||
description: Local development server | ||
paths: | ||
/todos: | ||
get: | ||
summary: Retrieve all to-dos | ||
description: Returns a list of all to-do items | ||
responses: | ||
'200': | ||
description: A list of to-do items | ||
content: | ||
application/json: | ||
schema: | ||
type: array | ||
items: | ||
$ref: '#/components/schemas/ToDo' | ||
post: | ||
summary: Create a new to-do | ||
description: Adds a new to-do item | ||
requestBody: | ||
required: true | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/NewToDo' | ||
responses: | ||
'201': | ||
description: To-do created successfully | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/ToDo' | ||
'400': | ||
description: Invalid input | ||
/todos/{id}: | ||
get: | ||
summary: Retrieve a single to-do item | ||
description: Returns the details of a specific to-do item by its ID | ||
parameters: | ||
- name: id | ||
in: path | ||
required: true | ||
schema: | ||
type: integer | ||
responses: | ||
'200': | ||
description: The requested to-do item | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/ToDo' | ||
'404': | ||
description: To-do not found | ||
put: | ||
summary: Update a to-do item | ||
description: Updates an existing to-do item by its ID | ||
parameters: | ||
- name: id | ||
in: path | ||
required: true | ||
schema: | ||
type: integer | ||
requestBody: | ||
required: true | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/NewToDo' | ||
responses: | ||
'200': | ||
description: To-do updated successfully | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/ToDo' | ||
'400': | ||
description: Invalid input | ||
'404': | ||
description: To-do not found | ||
delete: | ||
summary: Delete a to-do item | ||
description: Deletes a to-do item by its ID | ||
parameters: | ||
- name: id | ||
in: path | ||
required: true | ||
schema: | ||
type: integer | ||
responses: | ||
'204': | ||
description: To-do deleted successfully | ||
'404': | ||
description: To-do not found | ||
/register: | ||
post: | ||
summary: Register a user | ||
description: Registers a new user and expects a custom header `user-reg` | ||
parameters: | ||
- name: user-reg | ||
in: header | ||
required: true | ||
schema: | ||
type: string | ||
responses: | ||
'201': | ||
description: User registered successfully | ||
'400': | ||
description: Missing or invalid header | ||
components: | ||
schemas: | ||
ToDo: | ||
type: object | ||
properties: | ||
id: | ||
type: integer | ||
description: Unique identifier of the to-do item | ||
task: | ||
type: string | ||
description: The task description | ||
done: | ||
type: boolean | ||
description: Status of the to-do (completed or not) | ||
required: | ||
- id | ||
- task | ||
- done | ||
NewToDo: | ||
type: object | ||
properties: | ||
task: | ||
type: string | ||
description: The task description | ||
done: | ||
type: boolean | ||
description: Status of the to-do (completed or not) | ||
required: | ||
- task | ||
- done |
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 @@ | ||
# Build Stage | ||
FROM golang:1.22 AS build | ||
|
||
WORKDIR /app | ||
|
||
COPY go.mod go.sum ./ | ||
RUN go mod download | ||
|
||
COPY . ./ | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . | ||
|
||
# Deployment Stage | ||
FROM alpine:3.19.1 | ||
|
||
WORKDIR /root/ | ||
|
||
COPY --from=build /app/main . | ||
|
||
# Expose the application port | ||
EXPOSE 8080 | ||
|
||
CMD ["./main"] |
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,5 @@ | ||
module github.com/wso2/apk/code-challenge/todo-app | ||
|
||
go 1.22.6 | ||
|
||
require github.com/gorilla/mux v1.8.1 |
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,2 @@ | ||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= | ||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= |
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,102 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"log" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/gorilla/mux" | ||
) | ||
|
||
type Todo struct { | ||
ID int `json:"id"` | ||
Task string `json:"task"` | ||
Done bool `json:"done"` | ||
} | ||
|
||
var todos []Todo | ||
var nextID = 1 | ||
|
||
// Get all to-dos | ||
func getTodos(w http.ResponseWriter, r *http.Request) { | ||
json.NewEncoder(w).Encode(todos) | ||
} | ||
|
||
// Create a new to-do | ||
func createTodo(w http.ResponseWriter, r *http.Request) { | ||
var todo Todo | ||
_ = json.NewDecoder(r.Body).Decode(&todo) | ||
todo.ID = nextID | ||
nextID++ | ||
todos = append(todos, todo) | ||
json.NewEncoder(w).Encode(todo) | ||
} | ||
|
||
// Get a single to-do by ID | ||
func getTodoByID(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id, _ := strconv.Atoi(params["id"]) | ||
for _, todo := range todos { | ||
if todo.ID == id { | ||
json.NewEncoder(w).Encode(todo) | ||
return | ||
} | ||
} | ||
http.Error(w, "To-do not found", http.StatusNotFound) | ||
} | ||
|
||
// Update a to-do by ID | ||
func updateTodo(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id, _ := strconv.Atoi(params["id"]) | ||
for index, todo := range todos { | ||
if todo.ID == id { | ||
todos = append(todos[:index], todos[index+1:]...) | ||
var updatedTodo Todo | ||
_ = json.NewDecoder(r.Body).Decode(&updatedTodo) | ||
updatedTodo.ID = id | ||
todos = append(todos, updatedTodo) | ||
json.NewEncoder(w).Encode(updatedTodo) | ||
return | ||
} | ||
} | ||
http.Error(w, "To-do not found", http.StatusNotFound) | ||
} | ||
|
||
// Delete a to-do by ID | ||
func deleteTodo(w http.ResponseWriter, r *http.Request) { | ||
params := mux.Vars(r) | ||
id, _ := strconv.Atoi(params["id"]) | ||
for index, todo := range todos { | ||
if todo.ID == id { | ||
todos = append(todos[:index], todos[index+1:]...) | ||
json.NewEncoder(w).Encode(todos) | ||
return | ||
} | ||
} | ||
http.Error(w, "To-do not found", http.StatusNotFound) | ||
} | ||
|
||
// Register a user | ||
func registerUser(w http.ResponseWriter, r *http.Request) { | ||
regHeader := r.Header.Get("user-reg") | ||
if regHeader == "" { | ||
http.Error(w, "Missing user-reg header", http.StatusBadRequest) | ||
return | ||
} | ||
w.WriteHeader(http.StatusCreated) | ||
w.Write([]byte("User registered with header: " + regHeader)) | ||
} | ||
|
||
func main() { | ||
router := mux.NewRouter() | ||
router.HandleFunc("/todos", getTodos).Methods("GET") | ||
router.HandleFunc("/todos", createTodo).Methods("POST") | ||
router.HandleFunc("/todos/{id}", getTodoByID).Methods("GET") | ||
router.HandleFunc("/todos/{id}", updateTodo).Methods("PUT") | ||
router.HandleFunc("/todos/{id}", deleteTodo).Methods("DELETE") | ||
router.HandleFunc("/register", registerUser).Methods("POST") | ||
|
||
log.Fatal(http.ListenAndServe(":8080", router)) | ||
} |