Skip to content

Commit e5cb43e

Browse files
authored
Merge pull request #40 from devtron-labs/feat/currency-module-finops
feat: "currency rate conversion for finops"
2 parents a734324 + 347ec3b commit e5cb43e

File tree

19 files changed

+919
-295
lines changed

19 files changed

+919
-295
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Validate Pull Request
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
- synchronize
8+
- edited
9+
- reopened
10+
branches:
11+
- 'main'
12+
- 'release-**'
13+
- 'develop'
14+
- 'hotfix-**'
15+
# paths-ignore:
16+
# - 'docs/**'
17+
# - '.github/'
18+
# - 'CHANGELOG/'
19+
# - 'charts/'
20+
# - 'manifests/'
21+
# - 'sample-docker-templates/'
22+
jobs:
23+
validate-PR-issue:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v2
29+
30+
- name: Set up jq (for parsing JSON)
31+
run: sudo apt-get install -y jq
32+
33+
- name: PR Validation Script
34+
env:
35+
PR_BODY: ${{ github.event.pull_request.body }}
36+
PRNUM: ${{ github.event.pull_request.number }}
37+
TITLE: ${{ github.event.pull_request.title }}
38+
GH_TOKEN: ${{ github.token }}
39+
GH_PR_VALIDATOR_TOKEN: ${{ secrets.GH_PR_VALIDATOR_TOKEN }}
40+
BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
41+
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
42+
run: |
43+
wget https://raw.githubusercontent.com/devtron-labs/utilities/feat/central-pr-validator/.github/workflows/validateIssue.sh
44+
chmod +x validateIssue.sh
45+
./validateIssue.sh

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
central-api
1+
central-api
2+
.idea

Wire.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ package main
2121

2222
import (
2323
"github.com/devtron-labs/central-api/api"
24+
"github.com/devtron-labs/central-api/api/currency"
2425
util "github.com/devtron-labs/central-api/client"
25-
"github.com/devtron-labs/central-api/internal/logger"
2626
"github.com/devtron-labs/central-api/pkg"
27+
currencyPkg "github.com/devtron-labs/central-api/pkg/currency"
2728
blob_storage "github.com/devtron-labs/common-lib/blob-storage"
29+
"github.com/devtron-labs/common-lib/utils"
2830
"github.com/google/wire"
2931
)
3032

3133
func InitializeApp() (*App, error) {
3234
wire.Build(
33-
logger.NewSugardLogger,
35+
utils.NewSugardLogger,
3436
//sql.PgSqlWireSet,
3537
//releaseNote.NewReleaseNoteRepositoryImpl,
3638
//wire.Bind(new(releaseNote.ReleaseNoteRepository), new(*releaseNote.ReleaseNoteRepositoryImpl)),
@@ -50,6 +52,15 @@ func InitializeApp() (*App, error) {
5052

5153
pkg.NewCiBuildMetadataServiceImpl,
5254
wire.Bind(new(pkg.CiBuildMetadataService), new(*pkg.CiBuildMetadataServiceImpl)),
55+
56+
// Currency service dependencies
57+
currencyPkg.NewCurrencyConfig,
58+
currencyPkg.NewServiceImpl,
59+
wire.Bind(new(currencyPkg.Service), new(*currencyPkg.ServiceImpl)),
60+
currency.NewCurrencyRestHandlerImpl,
61+
wire.Bind(new(currency.CurrencyRestHandler), new(*currency.CurrencyRestHandlerImpl)),
62+
currency.NewRouter,
63+
wire.Bind(new(currency.Router), new(*currency.RouterImpl)),
5364
)
5465
return &App{}, nil
5566
}

api/RestHandler.go

Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package api
1818

1919
import (
20-
"encoding/json"
2120
"github.com/Masterminds/semver"
21+
"github.com/devtron-labs/central-api/api/handler"
2222
util "github.com/devtron-labs/central-api/client"
2323
"github.com/devtron-labs/central-api/common"
2424
"github.com/devtron-labs/central-api/pkg"
@@ -60,63 +60,32 @@ type RestHandlerImpl struct {
6060
ciBuildMetadataService pkg.CiBuildMetadataService
6161
}
6262

63-
func setupResponse(w *http.ResponseWriter, req *http.Request) {
64-
(*w).Header().Set("Access-Control-Allow-Origin", "*")
65-
(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
66-
(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
67-
(*w).Header().Set("Content-Type", "text/html; charset=utf-8")
68-
}
69-
70-
func (impl RestHandlerImpl) WriteJsonResp(w http.ResponseWriter, err error, respBody interface{}, status int) {
71-
response := common.Response{}
72-
response.Code = status
73-
response.Status = http.StatusText(status)
74-
if err == nil {
75-
response.Result = respBody
76-
} else {
77-
apiErr := &common.ApiError{}
78-
apiErr.Code = "000" // 000=unknown
79-
apiErr.InternalMessage = err.Error()
80-
apiErr.UserMessage = respBody
81-
response.Errors = []*common.ApiError{apiErr}
82-
83-
}
84-
b, err := json.Marshal(response)
85-
if err != nil {
86-
impl.logger.Errorw("error in marshaling err object", "err", err)
87-
status = 500
88-
}
89-
w.Header().Set("Content-Type", "application/json")
90-
w.WriteHeader(status)
91-
w.Write(b)
92-
}
93-
9463
func (impl *RestHandlerImpl) GetModules(w http.ResponseWriter, r *http.Request) {
9564
impl.logger.Debug("get all modules")
96-
setupResponse(&w, r)
65+
handler.SetupCorsOriginHeader(&w, r)
9766
modules, err := impl.releaseNoteService.GetModules()
9867
if err != nil {
99-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
68+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
10069
return
10170
}
102-
impl.WriteJsonResp(w, nil, modules, http.StatusOK)
71+
handler.WriteJsonResp(w, nil, modules, http.StatusOK)
10372
return
10473
}
10574

10675
func (impl *RestHandlerImpl) GetModulesV2(w http.ResponseWriter, r *http.Request) {
10776
impl.logger.Debug("get all modules")
108-
setupResponse(&w, r)
77+
handler.SetupCorsOriginHeader(&w, r)
10978
modules, err := impl.releaseNoteService.GetModulesV2()
11079
if err != nil {
111-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
80+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
11281
return
11382
}
114-
impl.WriteJsonResp(w, nil, modules, http.StatusOK)
83+
handler.WriteJsonResp(w, nil, modules, http.StatusOK)
11584
return
11685
}
11786

11887
func (impl *RestHandlerImpl) GetReleases(w http.ResponseWriter, r *http.Request) {
119-
setupResponse(&w, r)
88+
handler.SetupCorsOriginHeader(&w, r)
12089
impl.logger.Debug("get all releases")
12190
offset := 0
12291
size := 10
@@ -129,14 +98,14 @@ func (impl *RestHandlerImpl) GetReleases(w http.ResponseWriter, r *http.Request)
12998
if hasOffsetParam {
13099
offset, err = strconv.Atoi(offsetQueryParam)
131100
if err != nil {
132-
impl.WriteJsonResp(w, err, "invalid offset", http.StatusBadRequest)
101+
handler.WriteJsonResp(w, err, "invalid offset", http.StatusBadRequest)
133102
return
134103
}
135104
}
136105
if hasSizeParam {
137106
size, err = strconv.Atoi(sizeQueryParam)
138107
if err != nil {
139-
impl.WriteJsonResp(w, err, "invalid size", http.StatusBadRequest)
108+
handler.WriteJsonResp(w, err, "invalid size", http.StatusBadRequest)
140109
return
141110
}
142111
}
@@ -149,7 +118,7 @@ func (impl *RestHandlerImpl) GetReleases(w http.ResponseWriter, r *http.Request)
149118
//will fetch all the releases from cache and later apply size and offset filter
150119
response, err := impl.releaseNoteService.GetReleases(repository)
151120
if err != nil {
152-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
121+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
153122
return
154123
}
155124
if len(serverVersion) > 0 {
@@ -185,7 +154,7 @@ func (impl *RestHandlerImpl) GetReleases(w http.ResponseWriter, r *http.Request)
185154
response = make([]*common.Release, 0)
186155
}
187156

188-
impl.WriteJsonResp(w, nil, response, http.StatusOK)
157+
handler.WriteJsonResp(w, nil, response, http.StatusOK)
189158
return
190159
}
191160

@@ -200,61 +169,61 @@ func (impl *RestHandlerImpl) ReleaseWebhookHandler(w http.ResponseWriter, r *htt
200169
requestBodyBytes, err := ioutil.ReadAll(r.Body)
201170
if err != nil {
202171
impl.logger.Errorw("Cannot read the request body:", "err", err)
203-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
172+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
204173
return
205174
}
206175

207176
isValidSig := impl.webhookSecretValidator.ValidateSecret(r, requestBodyBytes)
208177
impl.logger.Debugw("Secret validation result ", "isValidSig", isValidSig)
209178
if !isValidSig {
210179
impl.logger.Error("Signature mismatch")
211-
impl.WriteJsonResp(w, err, nil, http.StatusUnauthorized)
180+
handler.WriteJsonResp(w, err, nil, http.StatusUnauthorized)
212181
return
213182
}
214183
// validate event type
215184
eventType := r.Header.Get(impl.client.GitHubConfig.GitHubEventTypeHeader)
216185
impl.logger.Debugw("webhook event type header", "eventType : ", eventType)
217186
if len(eventType) == 0 || eventType != bean.EventTypeRelease {
218187
impl.logger.Errorw("Event type not known ", eventType)
219-
impl.WriteJsonResp(w, err, nil, http.StatusBadRequest)
188+
handler.WriteJsonResp(w, err, nil, http.StatusBadRequest)
220189
return
221190
}
222191

223192
flag, err := impl.releaseNoteService.UpdateReleases(requestBodyBytes)
224193
if err != nil {
225-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
194+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
226195
return
227196
}
228-
impl.WriteJsonResp(w, err, flag, http.StatusOK)
197+
handler.WriteJsonResp(w, err, flag, http.StatusOK)
229198
return
230199
}
231200

232201
func (impl *RestHandlerImpl) GetModuleByName(w http.ResponseWriter, r *http.Request) {
233202
impl.logger.Debug("get module meta info by name")
234-
setupResponse(&w, r)
203+
handler.SetupCorsOriginHeader(&w, r)
235204
vars := mux.Vars(r)
236205
name := vars["name"]
237206
module, err := impl.releaseNoteService.GetModuleByName(name)
238207
if err != nil {
239-
impl.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
208+
handler.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
240209
return
241210
}
242-
impl.WriteJsonResp(w, nil, module, http.StatusOK)
211+
handler.WriteJsonResp(w, nil, module, http.StatusOK)
243212
return
244213
}
245214

246215
func (impl *RestHandlerImpl) GetDockerfileTemplateMetadata(w http.ResponseWriter, r *http.Request) {
247216
impl.logger.Debug("get all dockerfile template metadata")
248-
setupResponse(&w, r)
217+
handler.SetupCorsOriginHeader(&w, r)
249218
dockerfileTemplateMetadata := impl.ciBuildMetadataService.GetDockerfileTemplateMetadata()
250-
impl.WriteJsonResp(w, nil, dockerfileTemplateMetadata, http.StatusOK)
219+
handler.WriteJsonResp(w, nil, dockerfileTemplateMetadata, http.StatusOK)
251220
return
252221
}
253222
func (impl *RestHandlerImpl) GetBuildpackMetadata(w http.ResponseWriter, r *http.Request) {
254223
impl.logger.Debug("get all buildpack metadata")
255-
setupResponse(&w, r)
224+
handler.SetupCorsOriginHeader(&w, r)
256225
buildpackMetadata := impl.ciBuildMetadataService.GetBuildpackMetadata()
257-
impl.WriteJsonResp(w, nil, buildpackMetadata, http.StatusOK)
226+
handler.WriteJsonResp(w, nil, buildpackMetadata, http.StatusOK)
258227
return
259228
}
260229

api/Router.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,37 @@ package api
1818

1919
import (
2020
"encoding/json"
21-
"github.com/devtron-labs/central-api/common"
21+
"github.com/devtron-labs/central-api/api/currency"
22+
"github.com/devtron-labs/central-api/api/handler"
2223
"github.com/gorilla/mux"
2324
"go.uber.org/zap"
2425
"net/http"
2526
)
2627

2728
type MuxRouter struct {
28-
logger *zap.SugaredLogger
29-
Router *mux.Router
30-
restHandler RestHandler
29+
logger *zap.SugaredLogger
30+
Router *mux.Router
31+
restHandler RestHandler
32+
currencyRouter currency.Router
3133
}
3234

33-
func NewMuxRouter(logger *zap.SugaredLogger, restHandler RestHandler) *MuxRouter {
34-
return &MuxRouter{logger: logger, Router: mux.NewRouter(), restHandler: restHandler}
35+
func NewMuxRouter(logger *zap.SugaredLogger, restHandler RestHandler, currencyRouter currency.Router) *MuxRouter {
36+
return &MuxRouter{
37+
logger: logger,
38+
Router: mux.NewRouter(),
39+
restHandler: restHandler,
40+
currencyRouter: currencyRouter,
41+
}
3542
}
3643

3744
func (r MuxRouter) Init() {
3845
r.Router.StrictSlash(true)
3946
//r.Router.Handle("/metrics", promhttp.Handler())
4047
r.Router.Path("/health").HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
41-
setupResponse(&writer, request)
48+
handler.SetupCorsOriginHeader(&writer, request)
4249
writer.Header().Set("Content-Type", "application/json")
4350
writer.WriteHeader(200)
44-
response := common.Response{}
51+
response := handler.Response{}
4552
response.Code = 200
4653
response.Result = "OK"
4754
b, err := json.Marshal(response)
@@ -61,4 +68,9 @@ func (r MuxRouter) Init() {
6168
r.Router.Path("/module").
6269
Queries("name", "{name}").
6370
HandlerFunc(r.restHandler.GetModuleByName).Methods("GET")
71+
72+
// Create a sub-router for currency endpoints
73+
currencyRouter := r.Router.PathPrefix("/currency").Subrouter()
74+
// Initialize currency routes
75+
r.currencyRouter.InitCurrencyRoutes(currencyRouter)
6476
}

0 commit comments

Comments
 (0)