Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Flux app detail #5331

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
57e2b33
app list logic completed and proto is yet to generate
Jun 5, 2024
6852607
resolved the proto file issue
RajeevRanjan27 Jun 5, 2024
71dbc35
modified the proto and go routine call handling
RajeevRanjan27 Jun 5, 2024
8e74bfd
corrected the proto file datatype changes
RajeevRanjan27 Jun 5, 2024
8a8f760
applied the list of flux apps in given cluster
Jun 5, 2024
ae6f68a
resolved the conversations
Jun 5, 2024
3bf74dd
incorporated the review changes
Jun 5, 2024
27a0d9b
modified the fluxhandler and handlled the errros
Jun 6, 2024
668a1ad
resolved the coversations
Jun 6, 2024
5f3a04b
implemented the flush for streaming the data to client
Jun 7, 2024
41ee5d5
resolve the conflicts
Jun 7, 2024
53dc30a
incorporated comments
Jun 10, 2024
7d71b8c
Merge branch 'main' into flux-app-list
Jun 10, 2024
6137d5c
Added the spec file for fluxcd App listing
Jun 11, 2024
60fc2e2
Merge branch 'main' into flux-app-list
Jun 11, 2024
693ad55
Merge branch 'main' into flux-app-list
Jun 12, 2024
eb3befc
added the app type in the struct
RajeevRanjan27 Jun 13, 2024
87f0611
changed the fluxAppType data type
RajeevRanjan27 Jun 13, 2024
8f8b4a9
resolve
RajeevRanjan27 Jun 13, 2024
78df27f
resolve
RajeevRanjan27 Jun 13, 2024
80251ff
redefined the query params to process with
RajeevRanjan27 Jun 17, 2024
0c24d05
specs for flux app list added
RajeevRanjan27 Jun 17, 2024
134e08c
Merge branch 'main' into flux-app-list
RajeevRanjan27 Jun 17, 2024
3184637
Merge branch 'flux-app-list' into flux-app-detail
RajeevRanjan27 Jun 18, 2024
560a344
added the flux app detail
RajeevRanjan27 Jun 18, 2024
77db907
minor changes around the app listing response
RajeevRanjan27 Jun 18, 2024
74d47b5
Resolved the decoder appId function
RajeevRanjan27 Jun 19, 2024
4fb9e37
Added the spec for the app detail api
RajeevRanjan27 Jun 19, 2024
c82fa28
changed the field of flux app detail dto
RajeevRanjan27 Jun 25, 2024
9a855a6
taken merge from flux-app-list
RajeevRanjan27 Jun 25, 2024
a345b10
taken merge from main and grpc code resolved
RajeevRanjan27 Jun 25, 2024
252d199
taken merge from main and wire run
RajeevRanjan27 Jun 25, 2024
df08766
handled the error in listing of apps with errror field in grpc
RajeevRanjan27 Jun 27, 2024
4c23e11
Revert "taken merge from main and wire run"
RajeevRanjan27 Jun 27, 2024
9b09b56
Revert "handled the error in listing of apps with errror field in grpc"
RajeevRanjan27 Jul 1, 2024
24abc12
Added the error in the Listing of flux apps
RajeevRanjan27 Jul 1, 2024
b9106bf
Merge remote-tracking branch 'origin/flux-app-detail' into flux-app-d…
RajeevRanjan27 Jul 1, 2024
31148ad
generated the grpc code
RajeevRanjan27 Jul 1, 2024
efd2814
modified the logic for error handling in flux app listing and app det…
RajeevRanjan27 Jul 1, 2024
4e19367
Merge branch 'main' into flux-app-detail
RajeevRanjan27 Jul 1, 2024
5db5e18
took merge from main and run make
RajeevRanjan27 Jul 1, 2024
0eaf481
added the handler message for the root app i.e flux-system
RajeevRanjan27 Jul 1, 2024
7c03c65
minor changes: resolved the review comments after review
RajeevRanjan27 Jul 2, 2024
7726cdf
Merge branch 'main' into flux-app-detail
RajeevRanjan27 Jul 4, 2024
90982a9
took merge from main and executed the make cmd too
RajeevRanjan27 Jul 4, 2024
891a43d
added the debugger points in the flux app listing
RajeevRanjan27 Jul 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/devtron-labs/devtron/api/deployment"
"github.com/devtron-labs/devtron/api/devtronResource"
"github.com/devtron-labs/devtron/api/externalLink"
fluxApplication "github.com/devtron-labs/devtron/api/fluxApplication"
client "github.com/devtron-labs/devtron/api/helm-app"
"github.com/devtron-labs/devtron/api/infraConfig"
"github.com/devtron-labs/devtron/api/k8s"
Expand Down Expand Up @@ -193,7 +194,7 @@ func InitializeApp() (*App, error) {
build.BuildWireSet,
deployment2.DeploymentWireSet,
argoApplication.ArgoApplicationWireSet,

fluxApplication.FluxApplicationWireSet,
eventProcessor.EventProcessorWireSet,
workflow3.WorkflowWireSet,

Expand Down
11 changes: 11 additions & 0 deletions api/connector/Connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ func (impl PumpImpl) StartStreamWithTransformer(w http.ResponseWriter, recv func
f, ok := w.(http.Flusher)
if !ok {
http.Error(w, "unexpected server doesnt support streaming", http.StatusInternalServerError)
impl.logger.Debugw("unexpected server doesnt support streaming", "internal Server error", http.StatusInternalServerError)
}
if err != nil {
http.Error(w, errors.Details(err), http.StatusInternalServerError)
impl.logger.Debugw("error occurred during the setting up the flusher in wrote header ", "error", err)
}
w.Header().Set("Transfer-Encoding", "chunked")
w.Header().Set("Content-Type", "text/event-stream")
Expand All @@ -160,26 +162,35 @@ func (impl PumpImpl) StartStreamWithTransformer(w http.ResponseWriter, recv func
for {
resp, err := recv()
if err == io.EOF {
impl.logger.Debugw("error in receiving stream proto message ", "error", err)
return
}
impl.logger.Debugw("receiving stream proto message ", "response", resp, "error", err)

if err != nil {
impl.logger.Errorf("Error occurred while reading data from argocd %+v\n", err)
impl.handleForwardResponseStreamError(wroteHeader, w, err)
impl.logger.Debugw("Failed to send response chunk ", "error", err)

return
}
response := bean.Response{}
response.Result = transformer(resp)
buf, err := json.Marshal(response)
data := "data: " + string(buf)

if _, err = w.Write([]byte(data)); err != nil {
impl.logger.Errorf("Failed to send response chunk: %v", err)
impl.logger.Debugw("Failed to send response chunk ", "error", err)
return
}
wroteHeader = true
if _, err = w.Write(delimiter); err != nil {
impl.logger.Errorf("Failed to send delimiter chunk: %v", err)
impl.logger.Debugw("failed to send delimiter chunk ", "error", err)
return
}
impl.logger.Debugw("sending chunk data ", "data", data, "wroteheader", w)
f.Flush()
}
}
Expand Down
94 changes: 94 additions & 0 deletions api/fluxApplication/FluxApplicationRestHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package fluxApplication

import (
"errors"
"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
clientErrors "github.com/devtron-labs/devtron/pkg/errors"
"github.com/devtron-labs/devtron/pkg/fluxApplication"
"github.com/gorilla/mux"
"go.uber.org/zap"
"net/http"
)

type FluxApplicationRestHandler interface {
ListFluxApplications(w http.ResponseWriter, r *http.Request)
GetApplicationDetail(w http.ResponseWriter, r *http.Request)
}

type FluxApplicationRestHandlerImpl struct {
fluxApplicationService fluxApplication.FluxApplicationService
logger *zap.SugaredLogger
enforcer casbin.Enforcer
}

func NewFluxApplicationRestHandlerImpl(fluxApplicationService fluxApplication.FluxApplicationService,
logger *zap.SugaredLogger, enforcer casbin.Enforcer) *FluxApplicationRestHandlerImpl {
return &FluxApplicationRestHandlerImpl{
fluxApplicationService: fluxApplicationService,
logger: logger,
enforcer: enforcer,
}

}

func (handler *FluxApplicationRestHandlerImpl) ListFluxApplications(w http.ResponseWriter, r *http.Request) {

//handle super-admin RBAC
token := r.Header.Get("token")
if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}
v := r.URL.Query()
clusterIdString := v.Get("clusterIds")
var clusterIds []int
var err error

//handling when the clusterIds string is empty ,it will not support the
if len(clusterIdString) == 0 {
handler.logger.Errorw("error in getting cluster ids", "error", err, "clusterIds", clusterIds)
Copy link
Contributor

@prakash100198 prakash100198 Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this error "error in getting cluster ids" constant since used multiple times , also the comment above if check is incomplete

We can use util.ApiError with a proper http status code 404 not found error , and this error string can go in UserMessage as well as Internal message

If there are more such known error strings make them constant and leverage util.ApiError to send error resp with proper https status code

common.WriteJsonResp(w, errors.New("error in getting cluster ids"), nil, http.StatusBadRequest)
return
}
clusterIds, err = common.ExtractIntArrayQueryParam(w, r, "clusterIds")
if err != nil {
handler.logger.Errorw("error in getting cluster ids", "error", err, "clusterIds", clusterIds)
return
}
handler.logger.Debugw("extracted ClusterIds successfully ", "clusterIds", clusterIds)
handler.fluxApplicationService.ListFluxApplications(r.Context(), clusterIds, w)
}

func (handler *FluxApplicationRestHandlerImpl) GetApplicationDetail(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
appIdString := vars["appId"]
appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(appIdString)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
if appIdentifier.IsKustomizeApp == true && appIdentifier.Name == "flux-system" && appIdentifier.Namespace == "flux-system" {

Comment on lines +71 to +72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make "flux-system" constant

common.WriteJsonResp(w, errors.New("cannot proceed for the flux system root level "), nil, http.StatusBadRequest)
return
}

// handle super-admin RBAC
token := r.Header.Get("token")
if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}

res, err := handler.fluxApplicationService.GetFluxAppDetail(r.Context(), appIdentifier)
if err != nil {
apiError := clientErrors.ConvertToApiError(err)
if apiError != nil {
err = apiError
}
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, err, res, http.StatusOK)
}
27 changes: 27 additions & 0 deletions api/fluxApplication/FluxApplicationRouter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package fluxApplication

import (
"github.com/gorilla/mux"
)

type FluxApplicationRouter interface {
InitFluxApplicationRouter(fluxApplicationRouter *mux.Router)
}

type FluxApplicationRouterImpl struct {
fluxApplicationRestHandler FluxApplicationRestHandler
}

func NewFluxApplicationRouterImpl(fluxApplicationRestHandler FluxApplicationRestHandler) *FluxApplicationRouterImpl {
return &FluxApplicationRouterImpl{
fluxApplicationRestHandler: fluxApplicationRestHandler,
}
}

func (impl *FluxApplicationRouterImpl) InitFluxApplicationRouter(fluxApplicationRouter *mux.Router) {
fluxApplicationRouter.Path("").
Methods("GET").
HandlerFunc(impl.fluxApplicationRestHandler.ListFluxApplications)
fluxApplicationRouter.Path("/app").Queries("appId", "{appId}").
HandlerFunc(impl.fluxApplicationRestHandler.GetApplicationDetail).Methods("GET")
}
17 changes: 17 additions & 0 deletions api/fluxApplication/wire_fluxApplication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fluxApplication

import (
"github.com/devtron-labs/devtron/pkg/fluxApplication"
"github.com/google/wire"
)

var FluxApplicationWireSet = wire.NewSet(
fluxApplication.NewFluxApplicationServiceImpl,
wire.Bind(new(fluxApplication.FluxApplicationService), new(*fluxApplication.FluxApplicationServiceImpl)),

NewFluxApplicationRestHandlerImpl,
wire.Bind(new(FluxApplicationRestHandler), new(*FluxApplicationRestHandlerImpl)),

NewFluxApplicationRouterImpl,
wire.Bind(new(FluxApplicationRouter), new(*FluxApplicationRouterImpl)),
)
29 changes: 29 additions & 0 deletions api/helm-app/gRPC/applicationClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

type HelmAppClient interface {
ListApplication(ctx context.Context, req *AppListRequest) (ApplicationService_ListApplicationsClient, error)
ListFluxApplication(ctx context.Context, req *AppListRequest) (ApplicationService_ListFluxApplicationsClient, error)
GetAppDetail(ctx context.Context, in *AppDetailRequest) (*AppDetail, error)
GetResourceTreeForExternalResources(ctx context.Context, in *ExternalResourceTreeRequest) (*ResourceTreeResponse, error)
GetAppStatus(ctx context.Context, in *AppDetailRequest) (*AppStatus, error)
Expand All @@ -49,6 +50,7 @@ type HelmAppClient interface {
InstallReleaseWithCustomChart(ctx context.Context, in *HelmInstallCustomRequest) (*HelmInstallCustomResponse, error)
GetNotes(ctx context.Context, request *InstallReleaseRequest) (*ChartNotesResponse, error)
ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *RegistryCredential) (*OCIRegistryResponse, error)
GetExternalFluxAppDetail(ctx context.Context, in *FluxAppDetailRequest) (*FluxAppDetail, error)
}

type HelmAppClientImpl struct {
Expand Down Expand Up @@ -362,3 +364,30 @@ func (impl *HelmAppClientImpl) ValidateOCIRegistry(ctx context.Context, in *Regi
}
return response, nil
}
func (impl *HelmAppClientImpl) ListFluxApplication(ctx context.Context, req *AppListRequest) (ApplicationService_ListFluxApplicationsClient, error) {

applicationClient, err := impl.getApplicationClient()
if err != nil {
return nil, err
}
impl.logger.Debugw("established the app client successfully", "AppListRequest", req)
stream, err := applicationClient.ListFluxApplications(ctx, req)
if err != nil {
impl.logger.Debugw("error received from kubelink", "stream", stream, "error", err)

return nil, err
}
impl.logger.Debugw("stream received from kubelink", "stream", stream, "error", err)
return stream, nil
}
func (impl *HelmAppClientImpl) GetExternalFluxAppDetail(ctx context.Context, in *FluxAppDetailRequest) (*FluxAppDetail, error) {
applicationClient, err := impl.getApplicationClient()
if err != nil {
return nil, err
}
detail, err := applicationClient.GetFluxAppDetail(ctx, in)
if err != nil {
return nil, err
}
return detail, nil
}
Loading
Loading