lebrancconvas / fun-exercise-api

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fun Exercise: API Design and DevOps

Prerequisites

  • Go - 1.21.8 or higher
    • Mac: brew install go Homebrew or visit Go
    • Windows: choco install go Chocolatey
    • Linux: sudo apt-get install golang-go
    • Verify installation: go version
  • Docker
  • Swag - Generate Swagger Documentation
    • Install swag: go install github.com/swaggo/swag/cmd/swag@latest

Getting Started

  1. Clone the repository
  2. Open fun-exercise-api in your favorite Editor
  3. Before running the code, you need to make sure all of these tools are installed
  4. Run the following command to start the server
    docker-compose up
    
    go run main.go
  5. Open your browser and navigate to http://localhost:1323/api/v1/wallets
  6. You should see a list of wallets
  7. View Swagger documentation at http://localhost:1323/swagger/index.html
  8. You should see the Swagger documentation for the API

Swagger Documentation

  1. We've created a simple database schema for Wallet init.sql (see detail in docker-compose file)
erDiagram
	user_wallet {
		int id PK
		int user_id
		varchar user_name
		varchar wallet_name
		wallet_type wallet_type
		decimal balance
		timestamp created_at
    }

Table of Contents

Challenge 0: Display a list of wallets ✅

We've prepared a simple API, database schema for Wallets, and Swagger documentation

  • Simple API that displays a list of wallets http://localhost:1323/api/v1/wallets
  • Connecting to a Postgres database and query all wallets from user_wallet table
  • Create Swagger documentation for the API via swag init
  • wallet/handler.go - You'll see the comments pattern that is used to generate the Swagger documentation
// 	WalletHandler
//	@Summary		Get all wallets
//	@Description	Get all wallets
//	@Tags			wallet
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	Wallet
//	@Router			/api/v1/wallets [get]
//	@Failure		500	{object}	Err
func (h *Handler) WalletHandler(c echo.Context) error {
	wallets, err := h.store.Wallets() // Query all wallets
	if err != nil {
		return c.JSON(http.StatusInternalServerError, Err{Message: err.Error()})
	}
	return c.JSON(http.StatusOK, wallets)
}

Challenge 1: API - Using environment variables

As a developer, we need to deploy the application on the cloud, we need to prepare the application and make it ready for the cloud environment. In 12 Factors App, it's recommended to store the configuration in the environment variables.

This challenge is to replace the hardcode of the connection string in the code with the environment variables.

  1. Jump to the postgres package
  2. Edit postgres/postgres.go and replace the connection string with the environment variables instead.
  3. Feel free to refactoring the code and make it shorter for replacement
  4. Hint os.Getenv("XXX") - Get the environment variable

Expectation

No hardcode of the connection string in the code

Challenge 2: API - Write Unit Test for /ap/v1/wallets

As a developer, we need to make sure the code is working as expected.

This challenge is to write a unit test for the /api/v1/wallets endpoint and practice how to Test Double.

  1. Jump to the wallet_test.go file in the wallet package
  2. We've created draft of the test cases
  3. We need to implement the test cases and learn how to break dependency by Test Double
    func TestWallet(t *testing.T) {
    	t.Run("given unable to get wallets should return 500 and error message", func(t *testing.T) {
    
    	})
    
    	t.Run("given user able to getting wallet should return list of wallets", func(t *testing.T) {
    
    	})
    }
  4. Run the test cases go test -v ./...
  5. You can see an example coaching-week-3

Expectation

1. Test Double should be used to break the dependency for those test cases
2. All test cases should pass
3. Feel free to add more test cases

Challenge 3: API - Using Query Parameters

As a user, I want to filter the wallets based on the type of wallet.

This challenge is to use query parameters to filter the type of wallets ?wallet_type=Saving

  1. Jump to the wallet/handler.go file in the wallet package
  2. Add new logic for supporting query parameters
  3. Add Swagger document for that change via swag init
  4. Learn more about Query Parameters

Expectation

1. Filter the wallets based on the query parameters
2. Using appropriate HTTP methods and HTTP status code
3. JSON response should be returned
4. Swagger documentation should be implemented

Challenge 4: API - Using Path Parameters

As a user, I want to get the wallet for a specific user.

This challenge is to use path parameters to get the wallet for a specific user users/:id/wallets

Learn more about Path Parameters

Expectation

1. Get the wallet for the specific user
2. Using appropriate HTTP methods and HTTP status code
3. JSON response should be returned
4. Swagger documentation should be implemented

Challenge 5: API - Using Request Body to Create a Wallet

As a user, I want to create a wallet.

This challenge is to use the request body to create a wallet /api/v1/wallets

Expectation

1. Using appropriate HTTP methods and HTTP status code
2. JSON response should be return the wallet was just created
3. Swagger documentation should be implemented
4. Wallet should be created in the database

Challenge 6: API - Using Request Body to Update a Wallet

As a user, I want to update a wallet.

This challenge is to use the request body to update a wallet /api/v1/wallets

Expectation

1. Using appropriate HTTP methods and HTTP status code
2. JSON response should be return the wallet was just updated
3. Swagger documentation should be implemented
4. Wallet should be updated in the database

Challenge 7: API - Delete a Wallet

As a user, I want to delete a wallet out of specific user.

This challenge is to use the request body to delete a wallet /api/v1/users/:id/wallets

Expectation

1. Return appropriate response **HTTP status code**
2. Wallet should be deleted in the database

Challenge 8: DevOps - Dockerize the App - Multi-Stage Dockerfile

As a DevOps, we need to prepare the application for deployment and make it ready for the cloud environment.

This challenge is to create a Dockerfile for the Go application and make sure image size is optimized.

  1. Jump to Dockerfile
  2. Feel free to change base image, add more layers, and optimize the image size

Expectation

1. Create a Dockerfile for the Go application
2. Using multi-stage Dockerfile
3. The image size should be optimized
4. The image should be able to run the application (docker run)

Challenge 9: DevOps - Design a CI for running static code analysis and tests

As a DevOps, we need to design a CI for running static code analysis and tests.

This challenge is to design a CI (Github Action) for running static code analysis and tests.

  1. Look at the .github/workflows folder
  2. You can see the draft of the Github Action go-ci.yml
  3. Modify the go-ci.yml and implement the CI for running static code analysis and tests

Github Action Entry Point

Github Action

Github Action Workflow

Github Action

Expectation

1. The CI should be able to run static code analysis suche go vet ./... or staticcheck or golangci-lint
2. The CI should be able to run the tests
3. All tasks on the CI should be passed
4. Feel free to add more tasks - e.g. build the Docker image

About


Languages

Language:Go 99.5%Language:Dockerfile 0.5%