Skip to content

Commit 9eed68f

Browse files
authored
Merge pull request #3 from kriipke/feature/cluster-endpoints
Feature/cluster endpoints
2 parents 9b0d590 + 6a23b74 commit 9eed68f

29 files changed

+737
-213
lines changed

.github/workflows/docker-image.yml

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Docker Image CI
2+
3+
on:
4+
push:
5+
branches: [ "main", "develop", "feature/*" ]
6+
pull_request:
7+
branches: [ "main", "develop", "feature/*" ]
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: ${{ github.repository }}
11+
12+
jobs:
13+
14+
build:
15+
permissions: write-all
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
ref: feature/cluster-endpoints
22+
- name: Set up QEMU
23+
uses: docker/setup-qemu-action@v3
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
- name: Log in to the Container registry
27+
uses: docker/login-action@v3
28+
with:
29+
registry: ${{ env.REGISTRY }}
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
- name: Set up QEMU
33+
uses: docker/setup-qemu-action@v3
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v3
36+
- name: Extract metadata (tags, labels) for Docker
37+
id: meta
38+
uses: docker/metadata-action@v5
39+
with:
40+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
41+
42+
- name: Build and push Docker image
43+
uses: docker/build-push-action@v5
44+
with:
45+
context: .
46+
push: true
47+
tags: ${{ steps.meta.outputs.tags }}
48+
labels: ${{ steps.meta.outputs.labels }}
49+
platforms: linux/amd64,linux/arm64

.github/workflows/docker-push.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches:
6+
- '*'
7+
8+
jobs:
9+
docker:
10+
runs-on: ubuntu-latest
11+
steps:
12+
-
13+
name: Checkout
14+
uses: actions/checkout@v4
15+
with:
16+
ref: feature/cluster-endpoints
17+
-
18+
name: Set up QEMU
19+
uses: docker/setup-qemu-action@v3
20+
-
21+
name: Set up Docker Buildx
22+
uses: docker/setup-buildx-action@v3
23+
-
24+
name: Login to Docker Hub
25+
uses: docker/login-action@v3
26+
with:
27+
username: ${{ secrets.DOCKERHUB_USERNAME }}
28+
password: ${{ secrets.DOCKERHUB_TOKEN }}
29+
-
30+
name: Build and push
31+
uses: docker/build-push-action@v5
32+
with:
33+
context: .
34+
push: true
35+
tags: kriipke/console-api:latest

Dockerfile

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
FROM golang:1.22-alpine
2+
LABEL org.opencontainers.image.source="https://github.com/kriipke/console-api"
23
WORKDIR /app
34
COPY . .
45
RUN go mod download
@@ -8,6 +9,6 @@ RUN go build -o /app/api-bin ./cmd
89
FROM alpine:latest
910
WORKDIR /app
1011
COPY --from=0 /app/api-bin /app/api-bin
11-
COPY --from=0 /app/configs/app.env /app/configs/app.env
12+
#COPY --from=0 /app/configs/app.env /app/configs/app.env
1213
EXPOSE 8080
13-
CMD [ "/app//api-bin" ]
14+
CMD [ "/app/api-bin" ]

README.md

+30-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# GitOps Console
2+
13
## Overview
24

35
Secrets and other configuration for the `console-api` microserice should be located at:
@@ -14,17 +16,34 @@ Afterwards, edit `./configs/app.env` to contain:
1416
* credentials to a valid Postgres 14 database
1517
* SMTP credentials to a Mailtrap Inbox
1618

17-
## Project Specifications
18-
19-
RESOURCE METHOD ROUTE DESCRIPTION
20-
-----------------------------------------------------------------------------
21-
users GET /api/users/me Retrieve profile data
22-
auth POST /api/auth/register Create a new user
23-
auth POST /api/auth/login Sign in the user
24-
auth GET /api/auth/refresh Refresh the access token
25-
auth GET /api/auth/logout Logout the user
26-
password POST /api/auth/forgotpassword To request a reset link
27-
password PATCH /api/auth/resetpassword/:resetToken To reset the password
19+
## API Overview
20+
21+
METHOD METHOD ROUTE DESCRIPTION
22+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23+
24+
GET /api/healthchecker main.main.func1
25+
POST /api/auth/register github.com/kriipke/console-api/pkg/controllers.(*AuthController).SignUpUser-fm Create a new user
26+
POST /api/auth/login github.com/kriipke/console-api/pkg/controllers.(*AuthController).SignInUser-fm Sign in the user
27+
GET /api/auth/refresh github.com/kriipke/console-api/pkg/controllers.(*AuthController).RefreshAccessToken-fm Refresh the access token
28+
GET /api/auth/logout github.com/kriipke/console-api/pkg/controllers.(*AuthController).LogoutUser-fm Logout user
29+
POST /api/auth/forgotpassword github.com/kriipke/console-api/pkg/controllers.(*AuthController).ForgotPassword-fm To request a rest link
30+
PATCH /api/auth/resetpassword/:resetToken github.com/kriipke/console-api/pkg/controllers.(*AuthController).ResetPassword-fm To reset the password
31+
GET /api/auth/verifyemail/:verificationCode github.com/kriipke/console-api/pkg/controllers.(*AuthController).VerifyEmail-fm Verify Email address w/ verification code
32+
33+
GET /api/users/me github.com/kriipke/console-api/pkg/controllers.(*UserController).GetMe-fm Return whoami info
34+
35+
POST /api/posts/ github.com/kriipke/console-api/pkg/controllers.(*PostController).CreatePost-fm Create new post
36+
GET /api/posts/ github.com/kriipke/console-api/pkg/controllers.(*PostController).FindPosts-fm Get posts
37+
PUT /api/posts/:postId github.com/kriipke/console-api/pkg/controllers.(*PostController).UpdatePost-fm Updtae post
38+
GET /api/posts/:postId github.com/kriipke/console-api/pkg/controllers.(*PostController).FindPostById-fm Get post by ID
39+
DELETE /api/posts/:postId github.com/kriipke/console-api/pkg/controllers.(*PostController).DeletePost-fm Delete Post
40+
41+
POST /api/clusters/ github.com/kriipke/console-api/pkg/controllers.(*ClusterController).CreateCluster-fm Add new cluster to DB
42+
GET /api/clusters/ github.com/kriipke/console-api/pkg/controllers.(*ClusterController).FindClusters-fm Fetch clusters
43+
PUT /api/clusters/:clusterId github.com/kriipke/console-api/pkg/controllers.(*ClusterController).UpdateCluster-fm Update cluster info
44+
GET /api/clusters/:clusterId github.com/kriipke/console-api/pkg/controllers.(*ClusterController).FindClusterById-fm Get cluster info by ID
45+
DELETE /api/clusters/:clusterId github.com/kriipke/console-api/pkg/controllers.(*ClusterController).DeleteCluster-fm Delete Cluster
46+
2847

2948
* Project Structure
3049
- https://github.com/golang-standards/project-layout

cmd/main.go

+20-96
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,16 @@ package main
22

33
import (
44
"log"
5-
"time"
65
"strings"
76
"net/http"
8-
"github.com/gin-contrib/cors"
7+
//"github.com/gin-contrib/cors"
98
"github.com/gin-gonic/gin"
109
"github.com/kriipke/console-api/pkg/controllers"
1110
"github.com/kriipke/console-api/pkg/initializers"
1211
"github.com/kriipke/console-api/pkg/routes"
13-
"github.com/charmbracelet/lipgloss"
14-
"github.com/fatih/color"
15-
//"github.com/charmbracelet/lipgloss/table"
16-
12+
"github.com/kriipke/console-api/pkg/middleware"
1713
)
1814

19-
var style_keys = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("5"))
20-
var style_values = lipgloss.NewStyle().Foreground(lipgloss.Color("8"))
21-
2215
var (
2316
server *gin.Engine
2417
AuthController controllers.AuthController
@@ -29,6 +22,9 @@ var (
2922

3023
PostController controllers.PostController
3124
PostRouteController routes.PostRouteController
25+
26+
ClusterController controllers.ClusterController
27+
ClusterRouteController routes.ClusterRouteController
3228
)
3329
// function to convert an array to string
3430
func arrayToString(arr []string) string {
@@ -54,6 +50,9 @@ func init() {
5450
PostController = controllers.NewPostController(initializers.DB)
5551
PostRouteController = routes.NewRoutePostController(PostController)
5652

53+
ClusterController = controllers.NewClusterController(initializers.DB)
54+
ClusterRouteController = routes.NewRouteClusterController(ClusterController)
55+
5756
server = gin.Default()
5857
}
5958

@@ -63,20 +62,19 @@ func main() {
6362
log.Fatal("? Could not load environment variables", err)
6463
}
6564

66-
//consoleApiHost := os.Getenv("CONSOLE_API_HOST")
67-
//consoleApiPort := os.Getenv("CONSOLE_API_PORT")
68-
69-
corsConfig := cors.DefaultConfig()
70-
corsConfig.AllowOrigins = []string{"http://0.0.0.0:8080", config.ClientOrigin}
71-
//corsConfig.AllowAllOrigins = true
72-
//corsConfig.AllowCredentials = true
7365
// https://github.com/gin-gonic/gin/issues/2801
74-
//corsConfig.AddAllowMethods("OPTIONS")
66+
// corsConfig := cors.DefaultConfig()
67+
// corsConfig.AllowCredentials = true
68+
// corsConfig.AllowOrigins = []string{"http://localhost:8080", "http://localhost:3000", config.ClientOrigin}
69+
// corsConfig.AllowMethods = []string{"OPTIONS", "POST", "GET", "PUT"}
70+
// corsConfig.AllowHeader = []string{"Content-Type", "Authorization", "Origin"}
71+
72+
73+
// server.Use(cors.New(corsConfig))
7574

76-
//server.Use(cors.New(corsConfig))
77-
server.Use(corsMiddleware())
78-
server.Use(ResponseLogger())
79-
server.Use(RequestLogger())
75+
server.Use(middleware.CORSMiddleware())
76+
server.Use(middleware.ResponseLogger())
77+
server.Use(middleware.RequestLogger())
8078

8179
router := server.Group("/api")
8280
router.GET("/healthchecker", func(ctx *gin.Context) {
@@ -87,80 +85,6 @@ func main() {
8785
AuthRouteController.AuthRoute(router)
8886
UserRouteController.UserRoute(router)
8987
PostRouteController.PostRoute(router)
88+
ClusterRouteController.ClusterRoute(router)
9089
log.Fatal(server.Run(":" + config.ServerPort))
9190
}
92-
93-
94-
// https://jwstanly.com/blog/article/How+to+solve+SAM+403+Errors+on+CORS+Preflight
95-
func RequestLogger() gin.HandlerFunc {
96-
return func(c *gin.Context) {
97-
t := time.Now()
98-
99-
c1 := color.New(color.FgMagenta, color.Bold)
100-
c2 := color.New(color.FgWhite)
101-
c3 := color.New(color.FgYellow)
102-
c4 := color.New(color.FgCyan, color.Bold)
103-
c5 := color.New(color.FgWhite, color.Bold)
104-
105-
c.Next()
106-
107-
latency := time.Since(t)
108-
109-
c4.Printf("\n %s", c.Request.Method)
110-
c5.Printf("%s ", c.Request.RequestURI)
111-
c1.Printf("%s ", c.Request.Proto)
112-
c2.Printf("%s\n", latency)
113-
114-
for name, values := range c.Request.Header {
115-
for _, value := range values {
116-
c3.Printf(" %-20s:", name)
117-
c2.Printf("%-40s\n", value)
118-
}
119-
}
120-
}
121-
}
122-
123-
func ResponseLogger() gin.HandlerFunc {
124-
return func(c *gin.Context) {
125-
c.Writer.Header().Set("X-Content-Type-Options", "nosniff")
126-
127-
c.Next()
128-
129-
//c1 := color.New(color.FgMagenta, color.Bold)
130-
c2 := color.New(color.FgWhite)
131-
c3 := color.New(color.FgYellow)
132-
c4 := color.New(color.FgCyan, color.Bold)
133-
c5 := color.New(color.FgWhite, color.Bold)
134-
135-
c4.Printf("\n %s", c.Writer.Status())
136-
c4.Printf("%s ", c.Request.Method)
137-
c5.Printf("%s\n", c.Request.RequestURI)
138-
139-
for name, values := range c.Writer.Header() {
140-
for _, value := range values {
141-
c3.Printf(" %-40s:", name)
142-
c2.Printf("%-80s\n", value)
143-
}
144-
}
145-
146-
}
147-
}
148-
149-
150-
func corsMiddleware() gin.HandlerFunc {
151-
return func(c *gin.Context) {
152-
c.Writer.Header().Set("Access-Control-Allow-Origin",
153-
"http://localhost:3000, http://localhost:8080")
154-
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
155-
c.Writer.Header().Set("Access-Control-Allow-Methods", "*")
156-
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
157-
158-
if c.Request.Method == "OPTIONS" {
159-
c.AbortWithStatus(204)
160-
return
161-
}
162-
163-
c.Next()
164-
}
165-
}
166-

configs/app.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ POSTGRES_USER=pg
44
POSTGRES_PASSWORD=pass
55
POSTGRES_DB=opsdash
66
POSTGRES_PORT=5432
7+
POSTGRES_CA_CERT=/path/to/ca/cert.pem
78

89
# CONSOLE-API SERVER PORT
910
PORT=8080

configs/ca-postgres.crt

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIEQTCCAqmgAwIBAgIUCpLYyi8biSJO/5bq+Ge9r2DnGBIwDQYJKoZIhvcNAQEM
3+
BQAwOjE4MDYGA1UEAwwvODQwOGYyNmEtNTNiNC00ZjdkLWJjMjAtOGExZWQzNDRi
4+
NTU1IFByb2plY3QgQ0EwHhcNMjMwMzIxMDYwMDI0WhcNMzMwMzE4MDYwMDI0WjA6
5+
MTgwNgYDVQQDDC84NDA4ZjI2YS01M2I0LTRmN2QtYmMyMC04YTFlZDM0NGI1NTUg
6+
UHJvamVjdCBDQTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALUSqtmc
7+
OJSG3l2SDqM4u/CgQ7WldjRJhQKXYAr0551abE8TWyhL5Dp8YYOjwRWQrbz5tyN9
8+
2VxqGM7sQI0Scj7HzxRaexJmIBwFla167qzfEd8oVPG4b5BalhjnmVeYVtKEHJja
9+
oNyHyU9erRNABu5QUMZrKqJMT2j3WRjn5D3NFIphE3rX5ueoZmRxBVzWn91OaMWB
10+
SEZItW29EL8s/yOxNKyxQRfmWErcZsDGBMO3C0sxUQp+KJmkqPh7fJYTRaukFjMD
11+
encj4464v1jeApG9SohCLjokhQFQFgtxGxwBGqy7s6sUgtGxzwLSCrp3Sr9n8cYO
12+
I8EARxv75QMDaDwubBSbj/UXEtLkOEqkG4TbyRGL6R2PM8K9+m8Wrt8ROPbJdpmC
13+
RuTeNDJ+idTRExUvXQs1Z8NYbjz89hE/jkNCIzUpoHsjrQWVl6gOubLGNZMJohHf
14+
Sh1fq1b+cjn0fq+LPSyuIeWg1WSlifNRCOsTQj3L7wG1rN9UysiP58idIQIDAQAB
15+
oz8wPTAdBgNVHQ4EFgQUjRma869FdXwfU4vXHT8a8svkrqkwDwYDVR0TBAgwBgEB
16+
/wIBADALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEMBQADggGBAIHjvn4DZRvik+nP
17+
aTomudVMEfS+E8CLz+RzI4t+GVuPllZQXUsKZ0TpjrJ1GozMdGGN5lZY+LR+TnaW
18+
Xf8/PPlpckkcQxgevpIOCBd0+mjNzCP5Z0n8jjG1ygu9o0aeVm9quPCw2K4zvnnN
19+
ygICtI5rGPGXXLTs6VYzuBQrSV5m4YBSr9ewMKmmyJP1iENluKB75u14yNFDZYL2
20+
+dVTu9jCZkh9RfIdSn7tbvUt8G4QrjoJZWTv3ngvFdqISfH/o6TQBZSiKbabtwUU
21+
Rkbvmt+zyR7eeWfLIWMdEaX+rSP6sCej7TH3zRT5LPbS/+E3Mg6rHIEODf3RVqPo
22+
9qpOUFeH+n6gR5Xu0hEEMmjlyMsojuIx0SOun3hEzzQpehwB5HL+0KwIybiTFqil
23+
BIEFxHf/6VsI8tKhJQuMw7ii7cESWuKVR+Y59lGTVUFSpERFjfQaTqOu+4OG4FsI
24+
vXaYBpjcTf+TmzVTCV76VLYILWGQHdsM+6dcVvMGHS5u3xSwZQ==
25+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)