Skip to content

Commit d8b33fa

Browse files
External linkout (#1516)
* Added external links files * Added external links files in get all links * Added external links files in get all links * Added external links files in get all links * Added external links files in get all links * Added external links files in get all links * Added external links files in get all links * Added external links files in get all links * Column Name Refracted for External Links * Removed spaces * fetch all active ex links fixed * added db migration script and create ex links single to multi request modification * refactored and fixes * Added Extenal Links Specs file * fixes in rest handlers for external links and delete and update api * api responses structure fixes for external links * fix external linkout wire for hyperion * get all active links fetch apis empty handle * fetch active links fixes for duplicate items * modifications after testing on external links filter by clusters * external links update fixes * fix delete external link * fixes * added rbac for external links apis * rbac on external links * added cluster id in app details response * files, function, packages refactored for external links * updated on added on response for sorting for external apps * review changes - refactored, added inserts for monitoring tools * review changes * review changes * review changes - schema migration not null, and create transactional * review changes * wire gen external app * review changes * final review changes for external links * review changes Co-authored-by: nikeshDevtron <[email protected]>
1 parent 197568b commit d8b33fa

19 files changed

+1098
-28
lines changed

Wire.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/devtron-labs/devtron/api/connector"
3131
"github.com/devtron-labs/devtron/api/dashboardEvent"
3232
"github.com/devtron-labs/devtron/api/deployment"
33+
"github.com/devtron-labs/devtron/api/externalLink"
3334
client "github.com/devtron-labs/devtron/api/helm-app"
3435
"github.com/devtron-labs/devtron/api/restHandler"
3536
pipeline2 "github.com/devtron-labs/devtron/api/restHandler/app"
@@ -100,6 +101,7 @@ func InitializeApp() (*App, error) {
100101
wire.Build(
101102
// ----- wireset start
102103
sql.PgSqlWireSet,
104+
externalLink.ExternalLinkWireSet,
103105
team.TeamsWireSet,
104106
AuthWireSet,
105107
user.UserWireSet,

api/bean/AppView.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ type DeploymentDetailContainer struct {
106106
Deprecated bool `json:"deprecated"`
107107
K8sVersion string `json:"k8sVersion"`
108108
CiArtifactId int `json:"ciArtifactId"`
109+
ClusterId int `json:"clusterId"`
109110
}
110111

111112
type AppDetailContainer struct {
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
* Copyright (c) 2020 Devtron Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package externalLink
19+
20+
import (
21+
"encoding/json"
22+
"github.com/devtron-labs/devtron/api/restHandler/common"
23+
"github.com/devtron-labs/devtron/pkg/externalLink"
24+
"github.com/devtron-labs/devtron/pkg/user"
25+
"github.com/devtron-labs/devtron/pkg/user/casbin"
26+
"github.com/gorilla/mux"
27+
"github.com/juju/errors"
28+
"go.uber.org/zap"
29+
"net/http"
30+
"strconv"
31+
)
32+
33+
type ExternalLinkRestHandler interface {
34+
CreateExternalLinks(w http.ResponseWriter, r *http.Request)
35+
GetExternalLinkMonitoringTools(w http.ResponseWriter, r *http.Request)
36+
GetExternalLinks(w http.ResponseWriter, r *http.Request)
37+
UpdateExternalLink(w http.ResponseWriter, r *http.Request)
38+
DeleteExternalLink(w http.ResponseWriter, r *http.Request) // Update is_active to false link
39+
}
40+
type ExternalLinkRestHandlerImpl struct {
41+
logger *zap.SugaredLogger
42+
externalLinkService externalLink.ExternalLinkService
43+
userService user.UserService
44+
enforcer casbin.Enforcer
45+
}
46+
47+
func NewExternalLinkRestHandlerImpl(logger *zap.SugaredLogger,
48+
externalLinkService externalLink.ExternalLinkService,
49+
userService user.UserService,
50+
enforcer casbin.Enforcer,
51+
) *ExternalLinkRestHandlerImpl {
52+
return &ExternalLinkRestHandlerImpl{
53+
logger: logger,
54+
externalLinkService: externalLinkService,
55+
userService: userService,
56+
enforcer: enforcer,
57+
}
58+
}
59+
func (impl ExternalLinkRestHandlerImpl) CreateExternalLinks(w http.ResponseWriter, r *http.Request) {
60+
userId, err := impl.userService.GetLoggedInUser(r)
61+
if userId == 0 || err != nil {
62+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
63+
return
64+
}
65+
decoder := json.NewDecoder(r.Body)
66+
var beans []*externalLink.ExternalLinkDto
67+
err = decoder.Decode(&beans)
68+
if err != nil {
69+
impl.logger.Errorw("request err, SaveLink", "err", err, "payload", beans)
70+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
71+
return
72+
}
73+
74+
token := r.Header.Get("token")
75+
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionCreate, "*"); !ok {
76+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
77+
return
78+
}
79+
80+
res, err := impl.externalLinkService.Create(beans, userId)
81+
if err != nil {
82+
impl.logger.Errorw("service err, SaveLink", "err", err, "payload", beans)
83+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
84+
return
85+
}
86+
common.WriteJsonResp(w, err, res, http.StatusOK)
87+
}
88+
func (impl ExternalLinkRestHandlerImpl) GetExternalLinkMonitoringTools(w http.ResponseWriter, r *http.Request) {
89+
userId, err := impl.userService.GetLoggedInUser(r)
90+
if userId == 0 || err != nil {
91+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
92+
return
93+
}
94+
95+
// auth free api as we using this for multiple places
96+
97+
res, err := impl.externalLinkService.GetAllActiveTools()
98+
if err != nil {
99+
impl.logger.Errorw("service err, GetAllActiveTools", "err", err)
100+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
101+
return
102+
}
103+
common.WriteJsonResp(w, err, res, http.StatusOK)
104+
}
105+
func (impl ExternalLinkRestHandlerImpl) GetExternalLinks(w http.ResponseWriter, r *http.Request) {
106+
userId, err := impl.userService.GetLoggedInUser(r)
107+
if userId == 0 || err != nil {
108+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
109+
return
110+
}
111+
v := r.URL.Query()
112+
id := v.Get("clusterId")
113+
clusterId := 0
114+
if len(id) > 0 {
115+
clusterId, err = strconv.Atoi(id)
116+
if err != nil {
117+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
118+
return
119+
}
120+
}
121+
122+
//apply auth only in case when requested for all links
123+
if clusterId == 0 {
124+
token := r.Header.Get("token")
125+
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok {
126+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
127+
return
128+
}
129+
}
130+
131+
res, err := impl.externalLinkService.FetchAllActiveLinks(clusterId)
132+
if err != nil {
133+
impl.logger.Errorw("service err, FetchAllActive", "err", err)
134+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
135+
return
136+
}
137+
common.WriteJsonResp(w, err, res, http.StatusOK)
138+
}
139+
func (impl ExternalLinkRestHandlerImpl) UpdateExternalLink(w http.ResponseWriter, r *http.Request) {
140+
userId, err := impl.userService.GetLoggedInUser(r)
141+
if userId == 0 || err != nil {
142+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
143+
return
144+
}
145+
decoder := json.NewDecoder(r.Body)
146+
var bean externalLink.ExternalLinkDto
147+
err = decoder.Decode(&bean)
148+
if err != nil {
149+
impl.logger.Errorw("request err, Update Link", "err", err, "bean", bean)
150+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
151+
return
152+
}
153+
bean.UserId = userId
154+
155+
token := r.Header.Get("token")
156+
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*"); !ok {
157+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
158+
return
159+
}
160+
161+
impl.logger.Infow("request payload, UpdateLink", "err", err, "bean", bean)
162+
res, err := impl.externalLinkService.Update(&bean)
163+
if err != nil {
164+
impl.logger.Errorw("service err, Update Links", "err", err, "bean", bean)
165+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
166+
return
167+
}
168+
common.WriteJsonResp(w, err, res, http.StatusOK)
169+
}
170+
func (impl ExternalLinkRestHandlerImpl) DeleteExternalLink(w http.ResponseWriter, r *http.Request) {
171+
userId, err := impl.userService.GetLoggedInUser(r)
172+
if userId == 0 || err != nil {
173+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
174+
return
175+
}
176+
params := mux.Vars(r)
177+
id := params["id"]
178+
idi, err := strconv.Atoi(id)
179+
if err != nil {
180+
impl.logger.Errorw("request err, DeleteExternalLink", "err", err, "id", id)
181+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
182+
return
183+
}
184+
185+
token := r.Header.Get("token")
186+
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionDelete, "*"); !ok {
187+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
188+
return
189+
}
190+
191+
res, err := impl.externalLinkService.DeleteLink(idi, userId)
192+
if err != nil {
193+
impl.logger.Errorw("service err, delete Links", "err", err, "id", idi)
194+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
195+
return
196+
}
197+
common.WriteJsonResp(w, err, res, http.StatusOK)
198+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package externalLink
2+
3+
import (
4+
"github.com/gorilla/mux"
5+
)
6+
7+
type ExternalLinkRouter interface {
8+
InitExternalLinkRouter(gocdRouter *mux.Router)
9+
}
10+
type ExternalLinkRouterImpl struct {
11+
externalLinkRestHandler ExternalLinkRestHandler
12+
}
13+
14+
func NewExternalLinkRouterImpl(externalLinkRestHandler ExternalLinkRestHandler) *ExternalLinkRouterImpl {
15+
return &ExternalLinkRouterImpl{externalLinkRestHandler: externalLinkRestHandler}
16+
}
17+
18+
func (impl ExternalLinkRouterImpl) InitExternalLinkRouter(configRouter *mux.Router) {
19+
configRouter.Path("").HandlerFunc(impl.externalLinkRestHandler.CreateExternalLinks).Methods("POST")
20+
configRouter.Path("/tools").HandlerFunc(impl.externalLinkRestHandler.GetExternalLinkMonitoringTools).Methods("GET")
21+
configRouter.Path("").HandlerFunc(impl.externalLinkRestHandler.GetExternalLinks).Methods("GET")
22+
configRouter.Path("").HandlerFunc(impl.externalLinkRestHandler.UpdateExternalLink).Methods("PUT")
23+
configRouter.Path("").HandlerFunc(impl.externalLinkRestHandler.DeleteExternalLink).Queries("id", "{id}").Methods("DELETE")
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package externalLink
2+
3+
import (
4+
"github.com/devtron-labs/devtron/pkg/externalLink"
5+
"github.com/google/wire"
6+
)
7+
8+
//depends on sql,
9+
//TODO integrate user auth module
10+
11+
var ExternalLinkWireSet = wire.NewSet(
12+
externalLink.NewExternalLinkMonitoringToolRepositoryImpl,
13+
wire.Bind(new(externalLink.ExternalLinkMonitoringToolRepository), new(*externalLink.ExternalLinkMonitoringToolRepositoryImpl)),
14+
externalLink.NewExternalLinkClusterMappingRepositoryImpl,
15+
wire.Bind(new(externalLink.ExternalLinkClusterMappingRepository), new(*externalLink.ExternalLinkClusterMappingRepositoryImpl)),
16+
externalLink.NewExternalLinkRepositoryImpl,
17+
wire.Bind(new(externalLink.ExternalLinkRepository), new(*externalLink.ExternalLinkRepositoryImpl)),
18+
19+
20+
externalLink.NewExternalLinkServiceImpl,
21+
wire.Bind(new(externalLink.ExternalLinkService), new(*externalLink.ExternalLinkServiceImpl)),
22+
NewExternalLinkRestHandlerImpl,
23+
wire.Bind(new(ExternalLinkRestHandler), new(*ExternalLinkRestHandlerImpl)),
24+
NewExternalLinkRouterImpl,
25+
wire.Bind(new(ExternalLinkRouter), new(*ExternalLinkRouterImpl)),
26+
)

api/router/router.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/devtron-labs/devtron/api/cluster"
2626
"github.com/devtron-labs/devtron/api/dashboardEvent"
2727
"github.com/devtron-labs/devtron/api/deployment"
28+
"github.com/devtron-labs/devtron/api/externalLink"
2829
client "github.com/devtron-labs/devtron/api/helm-app"
2930
"github.com/devtron-labs/devtron/api/restHandler/common"
3031
"github.com/devtron-labs/devtron/api/router/pubsub"
@@ -88,16 +89,17 @@ type MuxRouter struct {
8889
ssoLoginRouter sso.SsoLoginRouter
8990
telemetryRouter TelemetryRouter
9091
telemetryWatcher telemetry.TelemetryEventClient
91-
bulkUpdateRouter BulkUpdateRouter
92-
WebhookListenerRouter WebhookListenerRouter
93-
appLabelsRouter AppLabelRouter
94-
coreAppRouter CoreAppRouter
95-
helmAppRouter client.HelmAppRouter
96-
k8sApplicationRouter k8s.K8sApplicationRouter
97-
pProfRouter PProfRouter
98-
deploymentConfigRouter deployment.DeploymentConfigRouter
99-
dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter
100-
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter
92+
bulkUpdateRouter BulkUpdateRouter
93+
WebhookListenerRouter WebhookListenerRouter
94+
appLabelsRouter AppLabelRouter
95+
coreAppRouter CoreAppRouter
96+
helmAppRouter client.HelmAppRouter
97+
k8sApplicationRouter k8s.K8sApplicationRouter
98+
pProfRouter PProfRouter
99+
deploymentConfigRouter deployment.DeploymentConfigRouter
100+
dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter
101+
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter
102+
externalLinkRouter externalLink.ExternalLinkRouter
101103
}
102104

103105
func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConfigRouter PipelineConfigRouter,
@@ -120,7 +122,7 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConf
120122
commonRouter CommonRouter, grafanaRouter GrafanaRouter, ssoLoginRouter sso.SsoLoginRouter, telemetryRouter TelemetryRouter, telemetryWatcher telemetry.TelemetryEventClient, bulkUpdateRouter BulkUpdateRouter, webhookListenerRouter WebhookListenerRouter, appLabelsRouter AppLabelRouter,
121123
coreAppRouter CoreAppRouter, helmAppRouter client.HelmAppRouter, k8sApplicationRouter k8s.K8sApplicationRouter,
122124
pProfRouter PProfRouter, deploymentConfigRouter deployment.DeploymentConfigRouter, dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter,
123-
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter) *MuxRouter {
125+
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter, externalLinkRouter externalLink.ExternalLinkRouter) *MuxRouter {
124126
r := &MuxRouter{
125127
Router: mux.NewRouter(),
126128
HelmRouter: HelmRouter,
@@ -176,6 +178,7 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConf
176178
deploymentConfigRouter: deploymentConfigRouter,
177179
dashboardTelemetryRouter: dashboardTelemetryRouter,
178180
commonDeploymentRouter: commonDeploymentRouter,
181+
externalLinkRouter: externalLinkRouter,
179182
}
180183
return r
181184
}
@@ -345,4 +348,7 @@ func (r MuxRouter) Init() {
345348
r.commonDeploymentRouter.Init(applicationSubRouter)
346349
//this router must placed after commonDeploymentRouter
347350
r.helmAppRouter.InitAppListRouter(applicationSubRouter)
351+
352+
externalLinkRouter := r.Router.PathPrefix("/orchestrator/external-links").Subrouter()
353+
r.externalLinkRouter.InitExternalLinkRouter(externalLinkRouter)
348354
}

cmd/external-app/router.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/devtron-labs/devtron/api/chartRepo"
99
"github.com/devtron-labs/devtron/api/cluster"
1010
"github.com/devtron-labs/devtron/api/dashboardEvent"
11+
"github.com/devtron-labs/devtron/api/externalLink"
1112
client "github.com/devtron-labs/devtron/api/helm-app"
1213
"github.com/devtron-labs/devtron/api/restHandler/common"
1314
"github.com/devtron-labs/devtron/api/sso"
@@ -39,6 +40,7 @@ type MuxRouter struct {
3940
appStoreDeploymentRouter appStoreDeployment.AppStoreDeploymentRouter
4041
dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter
4142
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter
43+
externalLinksRouter externalLink.ExternalLinkRouter
4244
}
4345

4446
func NewMuxRouter(
@@ -58,6 +60,7 @@ func NewMuxRouter(
5860
appStoreDeploymentRouter appStoreDeployment.AppStoreDeploymentRouter,
5961
dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter,
6062
commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter,
63+
externalLinkRouter externalLink.ExternalLinkRouter,
6164
) *MuxRouter {
6265
r := &MuxRouter{
6366
Router: mux.NewRouter(),
@@ -77,6 +80,7 @@ func NewMuxRouter(
7780
appStoreDeploymentRouter: appStoreDeploymentRouter,
7881
dashboardTelemetryRouter: dashboardTelemetryRouter,
7982
commonDeploymentRouter: commonDeploymentRouter,
83+
externalLinksRouter: externalLinkRouter,
8084
}
8185
return r
8286
}
@@ -162,4 +166,7 @@ func (r *MuxRouter) Init() {
162166
dashboardTelemetryRouter := r.Router.PathPrefix("/orchestrator/dashboard-event").Subrouter()
163167
r.dashboardTelemetryRouter.Init(dashboardTelemetryRouter)
164168
// dashboard event router ends
169+
170+
externalLinkRouter := r.Router.PathPrefix("/orchestrator/external-links").Subrouter()
171+
r.externalLinksRouter.InitExternalLinkRouter(externalLinkRouter)
165172
}

cmd/external-app/wire.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/devtron-labs/devtron/api/cluster"
1313
"github.com/devtron-labs/devtron/api/connector"
1414
"github.com/devtron-labs/devtron/api/dashboardEvent"
15+
"github.com/devtron-labs/devtron/api/externalLink"
1516
client "github.com/devtron-labs/devtron/api/helm-app"
1617
"github.com/devtron-labs/devtron/api/sso"
1718
"github.com/devtron-labs/devtron/api/team"
@@ -36,10 +37,12 @@ import (
3637

3738
func InitializeApp() (*App, error) {
3839
wire.Build(
40+
3941
sql.PgSqlWireSet,
4042
user.UserWireSet,
4143
sso.SsoConfigWireSet,
4244
AuthWireSet,
45+
externalLink.ExternalLinkWireSet,
4346
team.TeamsWireSet,
4447
cluster.ClusterWireSetEa,
4548
dashboard.DashboardWireSet,

0 commit comments

Comments
 (0)