Skip to content

feat: Flux added functionaities #5457

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

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 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
a8cd9b7
Added the rbac for the list Events and resource Deletion
RajeevRanjan27 Jun 26, 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
f67d3d6
Merge branch 'flux-app-detail' into flux-app-events
RajeevRanjan27 Jul 2, 2024
db84941
added the rbac for update of resources
RajeevRanjan27 Jul 2, 2024
7c03c65
minor changes: resolved the review comments after review
RajeevRanjan27 Jul 2, 2024
396c9d8
Merge branch 'flux-app-detail' into flux-app-events
RajeevRanjan27 Jul 4, 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
3c49408
completed rbac for list events, get resources, getTerminalSession,upd…
RajeevRanjan27 Jul 8, 2024
8883d75
Merge branch 'flux-app-detail' into flux-app-events
RajeevRanjan27 Jul 8, 2024
b12d7d1
removed the debugger points
RajeevRanjan27 Jul 8, 2024
b93a532
resolved the comment and incorporated the changes
RajeevRanjan27 Jul 9, 2024
760ec41
modified the verifyRbacForAppRequests function
RajeevRanjan27 Jul 9, 2024
a1c652e
Added the hibernate and unhibernate function for flux
RajeevRanjan27 Jul 9, 2024
22756a8
added the constants for making the redundency less
RajeevRanjan27 Jul 9, 2024
a488c9d
refactor the unhibernate code part
RajeevRanjan27 Jul 9, 2024
4768b34
removed the previous coded comments
RajeevRanjan27 Jul 9, 2024
748da5d
Merge branch 'main' into flux-added-feats
RajeevRanjan27 Jul 9, 2024
1fc0b49
resolved minor changes from comments
RajeevRanjan27 Jul 9, 2024
1099894
added the rbac for podLogs and k8sresourceurls
RajeevRanjan27 Jul 11, 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
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)
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 parsing 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" {

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)),
)
122 changes: 91 additions & 31 deletions api/helm-app/HelmAppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service"
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/EAMode"
clientErrors "github.com/devtron-labs/devtron/pkg/errors"
"github.com/devtron-labs/devtron/pkg/fluxApplication"
"github.com/devtron-labs/devtron/pkg/k8s"
"net/http"
"strconv"
"strings"
Expand Down Expand Up @@ -72,13 +74,14 @@ type HelmAppRestHandlerImpl struct {
userAuthService user.UserService
attributesService attributes.AttributesService
serverEnvConfig *serverEnvConfig.ServerEnvConfig
fluxApplication fluxApplication.FluxApplicationService
}

func NewHelmAppRestHandlerImpl(logger *zap.SugaredLogger,
helmAppService service2.HelmAppService, enforcer casbin.Enforcer,
clusterService cluster.ClusterService, enforcerUtil rbac.EnforcerUtilHelm,
appStoreDeploymentService service.AppStoreDeploymentService, installedAppService EAMode.InstalledAppDBService,
userAuthService user.UserService, attributesService attributes.AttributesService, serverEnvConfig *serverEnvConfig.ServerEnvConfig) *HelmAppRestHandlerImpl {
userAuthService user.UserService, attributesService attributes.AttributesService, serverEnvConfig *serverEnvConfig.ServerEnvConfig, fluxApplication fluxApplication.FluxApplicationService) *HelmAppRestHandlerImpl {
return &HelmAppRestHandlerImpl{
logger: logger,
helmAppService: helmAppService,
Expand All @@ -90,6 +93,7 @@ func NewHelmAppRestHandlerImpl(logger *zap.SugaredLogger,
userAuthService: userAuthService,
attributesService: attributesService,
serverEnvConfig: serverEnvConfig,
fluxApplication: fluxApplication,
}
}

Expand Down Expand Up @@ -159,68 +163,124 @@ func (handler *HelmAppRestHandlerImpl) GetApplicationDetail(w http.ResponseWrite
}

func (handler *HelmAppRestHandlerImpl) Hibernate(w http.ResponseWriter, r *http.Request) {
hibernateRequest := &openapi.HibernateRequest{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(hibernateRequest)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
appIdentifier, err := handler.helmAppService.DecodeAppId(*hibernateRequest.AppId)
hibernateRequest, err := decodeHibernateRequest(r)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}

// RBAC enforcer applying
rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
token := r.Header.Get("token")
ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject2)
if !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
var res []*openapi.HibernateStatus

if k8s.IsClusterStringContainsFluxField(*hibernateRequest.AppId) {
res, err = handler.handleFluxApplicationHibernate(r, token, hibernateRequest)
} else {
res, err = handler.handleHelmApplicationHibernate(r, token, hibernateRequest)
}
//RBAC enforcer Ends
res, err := handler.helmAppService.HibernateApplication(r.Context(), appIdentifier, hibernateRequest)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
common.WriteJsonResp(w, err, nil, service2.GetStatusCode(err))
return
}
common.WriteJsonResp(w, err, res, http.StatusOK)
}

func (handler *HelmAppRestHandlerImpl) UnHibernate(w http.ResponseWriter, r *http.Request) {
func decodeHibernateRequest(r *http.Request) (*openapi.HibernateRequest, error) {
hibernateRequest := &openapi.HibernateRequest{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(hibernateRequest)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
return nil, err
}
return hibernateRequest, nil
}

func (handler *HelmAppRestHandlerImpl) handleFluxApplicationHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) {
appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(*hibernateRequest.AppId)
if err != nil {
return nil, err
}

if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") {
return nil, errors.New("unauthorized")
}

return handler.fluxApplication.HibernateFluxApplication(r.Context(), appIdentifier, hibernateRequest)
}

func (handler *HelmAppRestHandlerImpl) handleHelmApplicationHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) {
appIdentifier, err := handler.helmAppService.DecodeAppId(*hibernateRequest.AppId)
if err != nil {
return nil, err
}
rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName(
appIdentifier.ClusterId,
appIdentifier.Namespace,
appIdentifier.ReleaseName,
)

ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) ||
handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject2)
if !ok {
return nil, errors.New("unauthorized")
}

return handler.helmAppService.HibernateApplication(r.Context(), appIdentifier, hibernateRequest)
}
func (handler *HelmAppRestHandlerImpl) UnHibernate(w http.ResponseWriter, r *http.Request) {
hibernateRequest, err := decodeHibernateRequest(r)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
// RBAC enforcer applying
rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
token := r.Header.Get("token")
var res []*openapi.HibernateStatus

ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject2)

if !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
if k8s.IsClusterStringContainsFluxField(*hibernateRequest.AppId) {
res, err = handler.handleFluxApplicationUnHibernate(r, token, hibernateRequest)
} else {
res, err = handler.handleHelmApplicationUnHibernate(r, token, hibernateRequest)
}
//RBAC enforcer Ends
res, err := handler.helmAppService.UnHibernateApplication(r.Context(), appIdentifier, hibernateRequest)

if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
common.WriteJsonResp(w, err, nil, service2.GetStatusCode(err))
return
}

common.WriteJsonResp(w, err, res, http.StatusOK)
}

func (handler *HelmAppRestHandlerImpl) handleFluxApplicationUnHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) {
appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(*hibernateRequest.AppId)
if err != nil {
return nil, err
}
if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") {
return nil, errors.New("unauthorized")
}
return handler.fluxApplication.UnHibernateFluxApplication(r.Context(), appIdentifier, hibernateRequest)
}

func (handler *HelmAppRestHandlerImpl) handleHelmApplicationUnHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) {
appIdentifier, err := handler.helmAppService.DecodeAppId(*hibernateRequest.AppId)
if err != nil {
return nil, err
}

rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName(
appIdentifier.ClusterId,
appIdentifier.Namespace,
appIdentifier.ReleaseName,
)

ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) ||
handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject2)
if !ok {
return nil, errors.New("unauthorized")
}

return handler.helmAppService.UnHibernateApplication(r.Context(), appIdentifier, hibernateRequest)
}

func (handler *HelmAppRestHandlerImpl) GetReleaseInfo(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
appId := vars["appId"]
Expand Down
24 changes: 24 additions & 0 deletions api/helm-app/gRPC/applicationClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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 @@ -50,6 +51,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 @@ -368,3 +370,25 @@ 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
}
stream, err := applicationClient.ListFluxApplications(ctx, req)
if err != nil {
return nil, 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