diff --git a/.gitbook.yaml b/.gitbook.yaml index 2f04cbca95..777f5fc9a3 100644 --- a/.gitbook.yaml +++ b/.gitbook.yaml @@ -16,7 +16,7 @@ redirects: setup/upgrade/devtron-upgrade-0.2.x-0.3.x: getting-started/upgrade/devtron-upgrade-0.2.x-0.3.x setup/global-configurations: user-guide/global-configurations/README.md setup/global-configurations/gitops: user-guide/global-configurations/gitops.md - setup/global-configurations/custom-charts: user-guide/global-configurations/custom-charts.md + setup/global-configurations/custom-charts: user-guide/global-configurations/deployment-charts.md setup/global-configurations/user-access: user-guide/global-configurations/authorization/user-access.md setup/global-configurations/external-links: user-guide/global-configurations/external-links.md setup/global-configurations/projects: user-guide/global-configurations/projects.md @@ -109,7 +109,7 @@ redirects: getting-started/global-configurations/filter-condition: user-guide/global-configurations/filter-condition.md getting-started/global-configurations/build-infra: user-guide/global-configurations/build-infra.md getting-started/global-configurations/gitops: user-guide/global-configurations/gitops.md - getting-started/global-configurations/custom-charts: user-guide/global-configurations/custom-charts.md + getting-started/global-configurations/custom-charts: user-guide/global-configurations/deployment-charts.md getting-started/global-configurations/external-links: user-guide/global-configurations/external-links.md getting-started/global-configurations/projects: user-guide/global-configurations/projects.md getting-started/global-configurations/manage-notification: user-guide/global-configurations/manage-notification.md @@ -127,4 +127,5 @@ redirects: user-guide/clusters: user-guide/resource-browser.md usage/clusters: user-guide/resource-browser.md global-configurations/authorization/sso-login/okta: user-guide/global-configurations/authorization/sso/okta.md - usage/applications/creating-application/ci-pipeline/ci-build-pre-post-plugins: user-guide/creating-application/workflow/ci-build-pre-post-plugins.md \ No newline at end of file + usage/applications/creating-application/ci-pipeline/ci-build-pre-post-plugins: user-guide/creating-application/workflow/ci-build-pre-post-plugins.md + global-configurations/custom-charts: user-guide/global-configurations/deployment-charts.md \ No newline at end of file diff --git a/Wire.go b/Wire.go index 9f7e7811ce..0d279f67c2 100644 --- a/Wire.go +++ b/Wire.go @@ -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" @@ -200,7 +201,7 @@ func InitializeApp() (*App, error) { build.BuildWireSet, deployment2.DeploymentWireSet, argoApplication.ArgoApplicationWireSet, - + fluxApplication.FluxApplicationWireSet, eventProcessor.EventProcessorWireSet, workflow3.WorkflowWireSet, diff --git a/api/bean/ConfigMapAndSecret.go b/api/bean/ConfigMapAndSecret.go index 184714a209..aad1a66ff9 100644 --- a/api/bean/ConfigMapAndSecret.go +++ b/api/bean/ConfigMapAndSecret.go @@ -32,6 +32,7 @@ type ConfigMapJson struct { type ConfigSecretRootJson struct { ConfigSecretJson ConfigSecretJson `json:"ConfigSecrets"` } + type ConfigSecretJson struct { Enabled bool `json:"enabled"` Secrets []*ConfigSecretMap `json:"secrets"` diff --git a/api/fluxApplication/FluxApplicationRestHandler.go b/api/fluxApplication/FluxApplicationRestHandler.go new file mode 100644 index 0000000000..7d947b2aae --- /dev/null +++ b/api/fluxApplication/FluxApplicationRestHandler.go @@ -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) +} diff --git a/api/fluxApplication/FluxApplicationRouter.go b/api/fluxApplication/FluxApplicationRouter.go new file mode 100644 index 0000000000..209a8b337b --- /dev/null +++ b/api/fluxApplication/FluxApplicationRouter.go @@ -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") +} diff --git a/api/fluxApplication/wire_fluxApplication.go b/api/fluxApplication/wire_fluxApplication.go new file mode 100644 index 0000000000..bfecc145fa --- /dev/null +++ b/api/fluxApplication/wire_fluxApplication.go @@ -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)), +) diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index 4fdd770fd8..059ce2ad9d 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -24,7 +24,10 @@ import ( service2 "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service" "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/EAMode" + "github.com/devtron-labs/devtron/pkg/argoApplication" clientErrors "github.com/devtron-labs/devtron/pkg/errors" + "github.com/devtron-labs/devtron/pkg/fluxApplication" + bean2 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" "net/http" "strconv" "strings" @@ -72,13 +75,16 @@ type HelmAppRestHandlerImpl struct { userAuthService user.UserService attributesService attributes.AttributesService serverEnvConfig *serverEnvConfig.ServerEnvConfig + fluxApplication fluxApplication.FluxApplicationService + argoApplication argoApplication.ArgoApplicationService } 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, argoApplication argoApplication.ArgoApplicationService, +) *HelmAppRestHandlerImpl { return &HelmAppRestHandlerImpl{ logger: logger, helmAppService: helmAppService, @@ -90,6 +96,8 @@ func NewHelmAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService: userAuthService, attributesService: attributesService, serverEnvConfig: serverEnvConfig, + fluxApplication: fluxApplication, + argoApplication: argoApplication, } } @@ -159,68 +167,180 @@ 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) + hibernateRequest, err := decodeHibernateRequest(r) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - appIdentifier, err := handler.helmAppService.DecodeAppId(*hibernateRequest.AppId) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return + + vars := mux.Vars(r) + var appType int + appTypeString := vars["appType"] //to check the type of app + if appTypeString == "" { + appType = 1 + } else { + appType, err = strconv.Atoi(appTypeString) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + } } - // 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 appType == bean2.ArgoAppType { + res, err = handler.handleArgoApplicationHibernate(r, token, hibernateRequest) + } else if appType == bean2.HelmAppType { + res, err = handler.handleHelmApplicationHibernate(r, token, hibernateRequest) + } else if appType == bean2.FluxAppType { + res, err = handler.handleFluxApplicationHibernate(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) handleArgoApplicationHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(*hibernateRequest.AppId) + if err != nil { + return nil, err + } + + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { + return nil, errors.New("unauthorized") } + + return handler.argoApplication.HibernateArgoApplication(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") - ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject2) + vars := mux.Vars(r) + var appType int + appTypeString := vars["appType"] //to check the type of app currently handled the case for identifying of external app types + if appTypeString == "" { + appType = 1 + } else { + appType, err = strconv.Atoi(appTypeString) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + } + } + token := r.Header.Get("token") + var res []*openapi.HibernateStatus - if !ok { - common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) - return + if appType == bean2.ArgoAppType { + res, err = handler.handleArgoApplicationUnHibernate(r, token, hibernateRequest) + } else if appType == bean2.HelmAppType { + res, err = handler.handleHelmApplicationUnHibernate(r, token, hibernateRequest) + } else if appType == bean2.FluxAppType { + res, err = handler.handleFluxApplicationUnHibernate(r, token, hibernateRequest) } - //RBAC enforcer Ends - res, err := handler.helmAppService.UnHibernateApplication(r.Context(), appIdentifier, hibernateRequest) + //if k8s.IsClusterStringContainsFluxField(*hibernateRequest.AppId) { + // res, err = handler.handleFluxApplicationUnHibernate(r, token, hibernateRequest) + //} else { + // res, err = handler.handleHelmApplicationUnHibernate(r, token, 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) handleArgoApplicationUnHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(*hibernateRequest.AppId) + if err != nil { + return nil, err + } + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { + return nil, errors.New("unauthorized") + } + return handler.argoApplication.UnHibernateArgoApplication(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"] diff --git a/api/helm-app/HelmAppRouter.go b/api/helm-app/HelmAppRouter.go index c9bad97436..2451c4ad23 100644 --- a/api/helm-app/HelmAppRouter.go +++ b/api/helm-app/HelmAppRouter.go @@ -42,8 +42,8 @@ func (impl *HelmAppRouterImpl) InitAppListRouter(helmRouter *mux.Router) { helmRouter.Path("/app/save-telemetry").Queries("appId", "{appId}"). HandlerFunc(impl.helmAppRestHandler.SaveHelmAppDetailsViewedTelemetryData).Methods("GET") - helmRouter.Path("/hibernate").HandlerFunc(impl.helmAppRestHandler.Hibernate).Methods("POST") - helmRouter.Path("/unhibernate").HandlerFunc(impl.helmAppRestHandler.UnHibernate).Methods("POST") + helmRouter.Path("/hibernate").Queries("appType", "{appType}").HandlerFunc(impl.helmAppRestHandler.Hibernate).Methods("POST") + helmRouter.Path("/unhibernate").Queries("appType", "{appType}").HandlerFunc(impl.helmAppRestHandler.UnHibernate).Methods("POST") // GetReleaseInfo used only for external apps helmRouter.Path("/release-info").Queries("appId", "{appId}"). diff --git a/api/helm-app/gRPC/applicationClient.go b/api/helm-app/gRPC/applicationClient.go index 79fae27ecb..ae2efe2922 100644 --- a/api/helm-app/gRPC/applicationClient.go +++ b/api/helm-app/gRPC/applicationClient.go @@ -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) @@ -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 { @@ -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 +} diff --git a/api/helm-app/gRPC/applist.pb.go b/api/helm-app/gRPC/applist.pb.go index f3de42acc9..6f5d4b7ae4 100644 --- a/api/helm-app/gRPC/applist.pb.go +++ b/api/helm-app/gRPC/applist.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.34.2 // protoc v3.9.1 // source: api/helm-app/gRPC/applist.proto @@ -354,6 +354,355 @@ func (x *ExternalResourceDetail) GetNamespace() string { return "" } +type FluxApplicationList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId int32 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"` + FluxApplication []*FluxApplication `protobuf:"bytes,2,rep,name=FluxApplication,proto3" json:"FluxApplication,omitempty"` + ErrorMsg string `protobuf:"bytes,3,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` + Errored bool `protobuf:"varint,4,opt,name=errored,proto3" json:"errored,omitempty"` +} + +func (x *FluxApplicationList) Reset() { + *x = FluxApplicationList{} + if protoimpl.UnsafeEnabled { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FluxApplicationList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FluxApplicationList) ProtoMessage() {} + +func (x *FluxApplicationList) ProtoReflect() protoreflect.Message { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FluxApplicationList.ProtoReflect.Descriptor instead. +func (*FluxApplicationList) Descriptor() ([]byte, []int) { + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{4} +} + +func (x *FluxApplicationList) GetClusterId() int32 { + if x != nil { + return x.ClusterId + } + return 0 +} + +func (x *FluxApplicationList) GetFluxApplication() []*FluxApplication { + if x != nil { + return x.FluxApplication + } + return nil +} + +func (x *FluxApplicationList) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + +func (x *FluxApplicationList) GetErrored() bool { + if x != nil { + return x.Errored + } + return false +} + +type FluxApplication struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + HealthStatus string `protobuf:"bytes,2,opt,name=healthStatus,proto3" json:"healthStatus,omitempty"` + SyncStatus string `protobuf:"bytes,3,opt,name=syncStatus,proto3" json:"syncStatus,omitempty"` + EnvironmentDetail *EnvironmentDetails `protobuf:"bytes,4,opt,name=environmentDetail,proto3" json:"environmentDetail,omitempty"` + FluxAppDeploymentType string `protobuf:"bytes,5,opt,name=fluxAppDeploymentType,proto3" json:"fluxAppDeploymentType,omitempty"` +} + +func (x *FluxApplication) Reset() { + *x = FluxApplication{} + if protoimpl.UnsafeEnabled { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FluxApplication) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FluxApplication) ProtoMessage() {} + +func (x *FluxApplication) ProtoReflect() protoreflect.Message { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FluxApplication.ProtoReflect.Descriptor instead. +func (*FluxApplication) Descriptor() ([]byte, []int) { + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{5} +} + +func (x *FluxApplication) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *FluxApplication) GetHealthStatus() string { + if x != nil { + return x.HealthStatus + } + return "" +} + +func (x *FluxApplication) GetSyncStatus() string { + if x != nil { + return x.SyncStatus + } + return "" +} + +func (x *FluxApplication) GetEnvironmentDetail() *EnvironmentDetails { + if x != nil { + return x.EnvironmentDetail + } + return nil +} + +func (x *FluxApplication) GetFluxAppDeploymentType() string { + if x != nil { + return x.FluxAppDeploymentType + } + return "" +} + +// ---------------flux external app detail------- +type FluxAppDetailRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterConfig *ClusterConfig `protobuf:"bytes,1,opt,name=clusterConfig,proto3" json:"clusterConfig,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + IsKustomizeApp bool `protobuf:"varint,4,opt,name=IsKustomizeApp,proto3" json:"IsKustomizeApp,omitempty"` +} + +func (x *FluxAppDetailRequest) Reset() { + *x = FluxAppDetailRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FluxAppDetailRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FluxAppDetailRequest) ProtoMessage() {} + +func (x *FluxAppDetailRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FluxAppDetailRequest.ProtoReflect.Descriptor instead. +func (*FluxAppDetailRequest) Descriptor() ([]byte, []int) { + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{6} +} + +func (x *FluxAppDetailRequest) GetClusterConfig() *ClusterConfig { + if x != nil { + return x.ClusterConfig + } + return nil +} + +func (x *FluxAppDetailRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *FluxAppDetailRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *FluxAppDetailRequest) GetIsKustomizeApp() bool { + if x != nil { + return x.IsKustomizeApp + } + return false +} + +type FluxAppDetail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FluxApplication *FluxApplication `protobuf:"bytes,1,opt,name=fluxApplication,proto3" json:"fluxApplication,omitempty"` + FluxAppStatusDetail *FluxAppStatusDetail `protobuf:"bytes,2,opt,name=FluxAppStatusDetail,proto3" json:"FluxAppStatusDetail,omitempty"` + ResourceTreeResponse *ResourceTreeResponse `protobuf:"bytes,3,opt,name=resourceTreeResponse,proto3" json:"resourceTreeResponse,omitempty"` +} + +func (x *FluxAppDetail) Reset() { + *x = FluxAppDetail{} + if protoimpl.UnsafeEnabled { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FluxAppDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FluxAppDetail) ProtoMessage() {} + +func (x *FluxAppDetail) ProtoReflect() protoreflect.Message { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FluxAppDetail.ProtoReflect.Descriptor instead. +func (*FluxAppDetail) Descriptor() ([]byte, []int) { + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{7} +} + +func (x *FluxAppDetail) GetFluxApplication() *FluxApplication { + if x != nil { + return x.FluxApplication + } + return nil +} + +func (x *FluxAppDetail) GetFluxAppStatusDetail() *FluxAppStatusDetail { + if x != nil { + return x.FluxAppStatusDetail + } + return nil +} + +func (x *FluxAppDetail) GetResourceTreeResponse() *ResourceTreeResponse { + if x != nil { + return x.ResourceTreeResponse + } + return nil +} + +type FluxAppStatusDetail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status string `protobuf:"bytes,1,opt,name=Status,proto3" json:"Status,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=Reason,proto3" json:"Reason,omitempty"` + Message string `protobuf:"bytes,3,opt,name=Message,proto3" json:"Message,omitempty"` +} + +func (x *FluxAppStatusDetail) Reset() { + *x = FluxAppStatusDetail{} + if protoimpl.UnsafeEnabled { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FluxAppStatusDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FluxAppStatusDetail) ProtoMessage() {} + +func (x *FluxAppStatusDetail) ProtoReflect() protoreflect.Message { + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FluxAppStatusDetail.ProtoReflect.Descriptor instead. +func (*FluxAppStatusDetail) Descriptor() ([]byte, []int) { + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{8} +} + +func (x *FluxAppStatusDetail) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *FluxAppStatusDetail) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *FluxAppStatusDetail) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +// ---------------flux external app detail ends here------- type DeployedAppList struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -368,7 +717,7 @@ type DeployedAppList struct { func (x *DeployedAppList) Reset() { *x = DeployedAppList{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[4] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -381,7 +730,7 @@ func (x *DeployedAppList) String() string { func (*DeployedAppList) ProtoMessage() {} func (x *DeployedAppList) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[4] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -394,7 +743,7 @@ func (x *DeployedAppList) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployedAppList.ProtoReflect.Descriptor instead. func (*DeployedAppList) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{4} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{9} } func (x *DeployedAppList) GetDeployedAppDetail() []*DeployedAppDetail { @@ -442,7 +791,7 @@ type DeployedAppDetail struct { func (x *DeployedAppDetail) Reset() { *x = DeployedAppDetail{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[5] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -455,7 +804,7 @@ func (x *DeployedAppDetail) String() string { func (*DeployedAppDetail) ProtoMessage() {} func (x *DeployedAppDetail) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[5] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -468,7 +817,7 @@ func (x *DeployedAppDetail) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployedAppDetail.ProtoReflect.Descriptor instead. func (*DeployedAppDetail) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{5} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{10} } func (x *DeployedAppDetail) GetAppId() string { @@ -533,7 +882,7 @@ type EnvironmentDetails struct { func (x *EnvironmentDetails) Reset() { *x = EnvironmentDetails{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[6] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -546,7 +895,7 @@ func (x *EnvironmentDetails) String() string { func (*EnvironmentDetails) ProtoMessage() {} func (x *EnvironmentDetails) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[6] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -559,7 +908,7 @@ func (x *EnvironmentDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use EnvironmentDetails.ProtoReflect.Descriptor instead. func (*EnvironmentDetails) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{6} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{11} } func (x *EnvironmentDetails) GetClusterName() string { @@ -598,7 +947,7 @@ type AppDetailRequest struct { func (x *AppDetailRequest) Reset() { *x = AppDetailRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[7] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -611,7 +960,7 @@ func (x *AppDetailRequest) String() string { func (*AppDetailRequest) ProtoMessage() {} func (x *AppDetailRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[7] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -624,7 +973,7 @@ func (x *AppDetailRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AppDetailRequest.ProtoReflect.Descriptor instead. func (*AppDetailRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{7} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{12} } func (x *AppDetailRequest) GetClusterConfig() *ClusterConfig { @@ -672,7 +1021,7 @@ type AppDetail struct { func (x *AppDetail) Reset() { *x = AppDetail{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[8] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -685,7 +1034,7 @@ func (x *AppDetail) String() string { func (*AppDetail) ProtoMessage() {} func (x *AppDetail) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[8] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -698,7 +1047,7 @@ func (x *AppDetail) ProtoReflect() protoreflect.Message { // Deprecated: Use AppDetail.ProtoReflect.Descriptor instead. func (*AppDetail) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{8} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{13} } func (x *AppDetail) GetApplicationStatus() string { @@ -764,7 +1113,7 @@ type AppStatus struct { func (x *AppStatus) Reset() { *x = AppStatus{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[9] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -777,7 +1126,7 @@ func (x *AppStatus) String() string { func (*AppStatus) ProtoMessage() {} func (x *AppStatus) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[9] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -790,7 +1139,7 @@ func (x *AppStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use AppStatus.ProtoReflect.Descriptor instead. func (*AppStatus) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{9} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{14} } func (x *AppStatus) GetApplicationStatus() string { @@ -834,7 +1183,7 @@ type ReleaseStatus struct { func (x *ReleaseStatus) Reset() { *x = ReleaseStatus{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[10] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -847,7 +1196,7 @@ func (x *ReleaseStatus) String() string { func (*ReleaseStatus) ProtoMessage() {} func (x *ReleaseStatus) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[10] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -860,7 +1209,7 @@ func (x *ReleaseStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseStatus.ProtoReflect.Descriptor instead. func (*ReleaseStatus) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{10} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{15} } func (x *ReleaseStatus) GetStatus() string { @@ -901,7 +1250,7 @@ type ChartMetadata struct { func (x *ChartMetadata) Reset() { *x = ChartMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[11] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -914,7 +1263,7 @@ func (x *ChartMetadata) String() string { func (*ChartMetadata) ProtoMessage() {} func (x *ChartMetadata) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[11] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -927,7 +1276,7 @@ func (x *ChartMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use ChartMetadata.ProtoReflect.Descriptor instead. func (*ChartMetadata) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{11} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{16} } func (x *ChartMetadata) GetChartName() string { @@ -984,7 +1333,7 @@ type ResourceTreeResponse struct { func (x *ResourceTreeResponse) Reset() { *x = ResourceTreeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[12] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -997,7 +1346,7 @@ func (x *ResourceTreeResponse) String() string { func (*ResourceTreeResponse) ProtoMessage() {} func (x *ResourceTreeResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[12] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1010,7 +1359,7 @@ func (x *ResourceTreeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceTreeResponse.ProtoReflect.Descriptor instead. func (*ResourceTreeResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{12} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{17} } func (x *ResourceTreeResponse) GetNodes() []*ResourceNode { @@ -1054,7 +1403,7 @@ type ResourceNode struct { func (x *ResourceNode) Reset() { *x = ResourceNode{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[13] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1067,7 +1416,7 @@ func (x *ResourceNode) String() string { func (*ResourceNode) ProtoMessage() {} func (x *ResourceNode) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[13] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1080,7 +1429,7 @@ func (x *ResourceNode) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceNode.ProtoReflect.Descriptor instead. func (*ResourceNode) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{13} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{18} } func (x *ResourceNode) GetGroup() string { @@ -1214,7 +1563,7 @@ type InfoItem struct { func (x *InfoItem) Reset() { *x = InfoItem{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[14] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1227,7 +1576,7 @@ func (x *InfoItem) String() string { func (*InfoItem) ProtoMessage() {} func (x *InfoItem) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[14] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1240,7 +1589,7 @@ func (x *InfoItem) ProtoReflect() protoreflect.Message { // Deprecated: Use InfoItem.ProtoReflect.Descriptor instead. func (*InfoItem) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{14} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{19} } func (x *InfoItem) GetName() string { @@ -1269,7 +1618,7 @@ type HealthStatus struct { func (x *HealthStatus) Reset() { *x = HealthStatus{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[15] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1282,7 +1631,7 @@ func (x *HealthStatus) String() string { func (*HealthStatus) ProtoMessage() {} func (x *HealthStatus) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[15] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1295,7 +1644,7 @@ func (x *HealthStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use HealthStatus.ProtoReflect.Descriptor instead. func (*HealthStatus) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{15} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{20} } func (x *HealthStatus) GetStatus() string { @@ -1323,7 +1672,7 @@ type ResourceNetworkingInfo struct { func (x *ResourceNetworkingInfo) Reset() { *x = ResourceNetworkingInfo{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[16] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1336,7 +1685,7 @@ func (x *ResourceNetworkingInfo) String() string { func (*ResourceNetworkingInfo) ProtoMessage() {} func (x *ResourceNetworkingInfo) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[16] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1349,7 +1698,7 @@ func (x *ResourceNetworkingInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceNetworkingInfo.ProtoReflect.Descriptor instead. func (*ResourceNetworkingInfo) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{16} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{21} } func (x *ResourceNetworkingInfo) GetLabels() map[string]string { @@ -1375,7 +1724,7 @@ type ResourceRef struct { func (x *ResourceRef) Reset() { *x = ResourceRef{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[17] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1388,7 +1737,7 @@ func (x *ResourceRef) String() string { func (*ResourceRef) ProtoMessage() {} func (x *ResourceRef) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[17] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1401,7 +1750,7 @@ func (x *ResourceRef) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceRef.ProtoReflect.Descriptor instead. func (*ResourceRef) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{17} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{22} } func (x *ResourceRef) GetGroup() string { @@ -1462,7 +1811,7 @@ type PodMetadata struct { func (x *PodMetadata) Reset() { *x = PodMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[18] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1475,7 +1824,7 @@ func (x *PodMetadata) String() string { func (*PodMetadata) ProtoMessage() {} func (x *PodMetadata) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[18] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1488,7 +1837,7 @@ func (x *PodMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PodMetadata.ProtoReflect.Descriptor instead. func (*PodMetadata) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{18} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{23} } func (x *PodMetadata) GetName() string { @@ -1545,7 +1894,7 @@ type EphemeralContainerData struct { func (x *EphemeralContainerData) Reset() { *x = EphemeralContainerData{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[19] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1558,7 +1907,7 @@ func (x *EphemeralContainerData) String() string { func (*EphemeralContainerData) ProtoMessage() {} func (x *EphemeralContainerData) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[19] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1571,7 +1920,7 @@ func (x *EphemeralContainerData) ProtoReflect() protoreflect.Message { // Deprecated: Use EphemeralContainerData.ProtoReflect.Descriptor instead. func (*EphemeralContainerData) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{19} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{24} } func (x *EphemeralContainerData) GetName() string { @@ -1600,7 +1949,7 @@ type HibernateRequest struct { func (x *HibernateRequest) Reset() { *x = HibernateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[20] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1613,7 +1962,7 @@ func (x *HibernateRequest) String() string { func (*HibernateRequest) ProtoMessage() {} func (x *HibernateRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[20] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1626,7 +1975,7 @@ func (x *HibernateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HibernateRequest.ProtoReflect.Descriptor instead. func (*HibernateRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{20} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{25} } func (x *HibernateRequest) GetClusterConfig() *ClusterConfig { @@ -1658,7 +2007,7 @@ type ObjectIdentifier struct { func (x *ObjectIdentifier) Reset() { *x = ObjectIdentifier{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[21] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1671,7 +2020,7 @@ func (x *ObjectIdentifier) String() string { func (*ObjectIdentifier) ProtoMessage() {} func (x *ObjectIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[21] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1684,7 +2033,7 @@ func (x *ObjectIdentifier) ProtoReflect() protoreflect.Message { // Deprecated: Use ObjectIdentifier.ProtoReflect.Descriptor instead. func (*ObjectIdentifier) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{21} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{26} } func (x *ObjectIdentifier) GetGroup() string { @@ -1735,7 +2084,7 @@ type HibernateStatus struct { func (x *HibernateStatus) Reset() { *x = HibernateStatus{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[22] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1748,7 +2097,7 @@ func (x *HibernateStatus) String() string { func (*HibernateStatus) ProtoMessage() {} func (x *HibernateStatus) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[22] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1761,7 +2110,7 @@ func (x *HibernateStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use HibernateStatus.ProtoReflect.Descriptor instead. func (*HibernateStatus) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{22} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{27} } func (x *HibernateStatus) GetTargetObject() *ObjectIdentifier { @@ -1796,7 +2145,7 @@ type HibernateResponse struct { func (x *HibernateResponse) Reset() { *x = HibernateResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[23] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1809,7 +2158,7 @@ func (x *HibernateResponse) String() string { func (*HibernateResponse) ProtoMessage() {} func (x *HibernateResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[23] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1822,7 +2171,7 @@ func (x *HibernateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HibernateResponse.ProtoReflect.Descriptor instead. func (*HibernateResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{23} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{28} } func (x *HibernateResponse) GetStatus() []*HibernateStatus { @@ -1848,7 +2197,7 @@ type HelmAppDeploymentDetail struct { func (x *HelmAppDeploymentDetail) Reset() { *x = HelmAppDeploymentDetail{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[24] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1861,7 +2210,7 @@ func (x *HelmAppDeploymentDetail) String() string { func (*HelmAppDeploymentDetail) ProtoMessage() {} func (x *HelmAppDeploymentDetail) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[24] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1874,7 +2223,7 @@ func (x *HelmAppDeploymentDetail) ProtoReflect() protoreflect.Message { // Deprecated: Use HelmAppDeploymentDetail.ProtoReflect.Descriptor instead. func (*HelmAppDeploymentDetail) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{24} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{29} } func (x *HelmAppDeploymentDetail) GetChartMetadata() *ChartMetadata { @@ -1930,7 +2279,7 @@ type HelmAppDeploymentHistory struct { func (x *HelmAppDeploymentHistory) Reset() { *x = HelmAppDeploymentHistory{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[25] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1943,7 +2292,7 @@ func (x *HelmAppDeploymentHistory) String() string { func (*HelmAppDeploymentHistory) ProtoMessage() {} func (x *HelmAppDeploymentHistory) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[25] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1956,7 +2305,7 @@ func (x *HelmAppDeploymentHistory) ProtoReflect() protoreflect.Message { // Deprecated: Use HelmAppDeploymentHistory.ProtoReflect.Descriptor instead. func (*HelmAppDeploymentHistory) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{25} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{30} } func (x *HelmAppDeploymentHistory) GetDeploymentHistory() []*HelmAppDeploymentDetail { @@ -1982,7 +2331,7 @@ type ReleaseInfo struct { func (x *ReleaseInfo) Reset() { *x = ReleaseInfo{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[26] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1995,7 +2344,7 @@ func (x *ReleaseInfo) String() string { func (*ReleaseInfo) ProtoMessage() {} func (x *ReleaseInfo) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[26] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2008,7 +2357,7 @@ func (x *ReleaseInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseInfo.ProtoReflect.Descriptor instead. func (*ReleaseInfo) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{26} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{31} } func (x *ReleaseInfo) GetDeployedAppDetail() *DeployedAppDetail { @@ -2067,7 +2416,7 @@ type ObjectRequest struct { func (x *ObjectRequest) Reset() { *x = ObjectRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[27] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2080,7 +2429,7 @@ func (x *ObjectRequest) String() string { func (*ObjectRequest) ProtoMessage() {} func (x *ObjectRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[27] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2093,7 +2442,7 @@ func (x *ObjectRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ObjectRequest.ProtoReflect.Descriptor instead. func (*ObjectRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{27} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{32} } func (x *ObjectRequest) GetClusterConfig() *ClusterConfig { @@ -2135,7 +2484,7 @@ type DesiredManifestResponse struct { func (x *DesiredManifestResponse) Reset() { *x = DesiredManifestResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[28] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2148,7 +2497,7 @@ func (x *DesiredManifestResponse) String() string { func (*DesiredManifestResponse) ProtoMessage() {} func (x *DesiredManifestResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[28] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2161,7 +2510,7 @@ func (x *DesiredManifestResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DesiredManifestResponse.ProtoReflect.Descriptor instead. func (*DesiredManifestResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{28} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{33} } func (x *DesiredManifestResponse) GetManifest() string { @@ -2182,7 +2531,7 @@ type UninstallReleaseResponse struct { func (x *UninstallReleaseResponse) Reset() { *x = UninstallReleaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[29] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2195,7 +2544,7 @@ func (x *UninstallReleaseResponse) String() string { func (*UninstallReleaseResponse) ProtoMessage() {} func (x *UninstallReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[29] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2208,7 +2557,7 @@ func (x *UninstallReleaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UninstallReleaseResponse.ProtoReflect.Descriptor instead. func (*UninstallReleaseResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{29} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{34} } func (x *UninstallReleaseResponse) GetSuccess() bool { @@ -2231,7 +2580,7 @@ type ReleaseIdentifier struct { func (x *ReleaseIdentifier) Reset() { *x = ReleaseIdentifier{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[30] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2244,7 +2593,7 @@ func (x *ReleaseIdentifier) String() string { func (*ReleaseIdentifier) ProtoMessage() {} func (x *ReleaseIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[30] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2257,7 +2606,7 @@ func (x *ReleaseIdentifier) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseIdentifier.ProtoReflect.Descriptor instead. func (*ReleaseIdentifier) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{30} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{35} } func (x *ReleaseIdentifier) GetClusterConfig() *ClusterConfig { @@ -2297,7 +2646,7 @@ type UpgradeReleaseRequest struct { func (x *UpgradeReleaseRequest) Reset() { *x = UpgradeReleaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[31] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2310,7 +2659,7 @@ func (x *UpgradeReleaseRequest) String() string { func (*UpgradeReleaseRequest) ProtoMessage() {} func (x *UpgradeReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[31] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2323,7 +2672,7 @@ func (x *UpgradeReleaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpgradeReleaseRequest.ProtoReflect.Descriptor instead. func (*UpgradeReleaseRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{31} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{36} } func (x *UpgradeReleaseRequest) GetReleaseIdentifier() *ReleaseIdentifier { @@ -2379,7 +2728,7 @@ type UpgradeReleaseResponse struct { func (x *UpgradeReleaseResponse) Reset() { *x = UpgradeReleaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[32] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2392,7 +2741,7 @@ func (x *UpgradeReleaseResponse) String() string { func (*UpgradeReleaseResponse) ProtoMessage() {} func (x *UpgradeReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[32] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2405,7 +2754,7 @@ func (x *UpgradeReleaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpgradeReleaseResponse.ProtoReflect.Descriptor instead. func (*UpgradeReleaseResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{32} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{37} } func (x *UpgradeReleaseResponse) GetSuccess() bool { @@ -2427,7 +2776,7 @@ type DeploymentDetailRequest struct { func (x *DeploymentDetailRequest) Reset() { *x = DeploymentDetailRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[33] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2440,7 +2789,7 @@ func (x *DeploymentDetailRequest) String() string { func (*DeploymentDetailRequest) ProtoMessage() {} func (x *DeploymentDetailRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[33] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2453,7 +2802,7 @@ func (x *DeploymentDetailRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeploymentDetailRequest.ProtoReflect.Descriptor instead. func (*DeploymentDetailRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{33} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{38} } func (x *DeploymentDetailRequest) GetReleaseIdentifier() *ReleaseIdentifier { @@ -2482,7 +2831,7 @@ type DeploymentDetailResponse struct { func (x *DeploymentDetailResponse) Reset() { *x = DeploymentDetailResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[34] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2495,7 +2844,7 @@ func (x *DeploymentDetailResponse) String() string { func (*DeploymentDetailResponse) ProtoMessage() {} func (x *DeploymentDetailResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[34] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2508,7 +2857,7 @@ func (x *DeploymentDetailResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeploymentDetailResponse.ProtoReflect.Descriptor instead. func (*DeploymentDetailResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{34} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{39} } func (x *DeploymentDetailResponse) GetManifest() string { @@ -2540,7 +2889,7 @@ type ChartRepository struct { func (x *ChartRepository) Reset() { *x = ChartRepository{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[35] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2553,7 +2902,7 @@ func (x *ChartRepository) String() string { func (*ChartRepository) ProtoMessage() {} func (x *ChartRepository) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[35] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2566,7 +2915,7 @@ func (x *ChartRepository) ProtoReflect() protoreflect.Message { // Deprecated: Use ChartRepository.ProtoReflect.Descriptor instead. func (*ChartRepository) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{35} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{40} } func (x *ChartRepository) GetName() string { @@ -2626,7 +2975,7 @@ type InstallReleaseRequest struct { func (x *InstallReleaseRequest) Reset() { *x = InstallReleaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[36] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2639,7 +2988,7 @@ func (x *InstallReleaseRequest) String() string { func (*InstallReleaseRequest) ProtoMessage() {} func (x *InstallReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[36] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2652,7 +3001,7 @@ func (x *InstallReleaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InstallReleaseRequest.ProtoReflect.Descriptor instead. func (*InstallReleaseRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{36} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{41} } func (x *InstallReleaseRequest) GetReleaseIdentifier() *ReleaseIdentifier { @@ -2750,7 +3099,7 @@ type BulkInstallReleaseRequest struct { func (x *BulkInstallReleaseRequest) Reset() { *x = BulkInstallReleaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[37] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2763,7 +3112,7 @@ func (x *BulkInstallReleaseRequest) String() string { func (*BulkInstallReleaseRequest) ProtoMessage() {} func (x *BulkInstallReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[37] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2776,7 +3125,7 @@ func (x *BulkInstallReleaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BulkInstallReleaseRequest.ProtoReflect.Descriptor instead. func (*BulkInstallReleaseRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{37} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{42} } func (x *BulkInstallReleaseRequest) GetBulkInstallReleaseRequest() []*InstallReleaseRequest { @@ -2797,7 +3146,7 @@ type InstallReleaseResponse struct { func (x *InstallReleaseResponse) Reset() { *x = InstallReleaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[38] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2810,7 +3159,7 @@ func (x *InstallReleaseResponse) String() string { func (*InstallReleaseResponse) ProtoMessage() {} func (x *InstallReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[38] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2823,7 +3172,7 @@ func (x *InstallReleaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InstallReleaseResponse.ProtoReflect.Descriptor instead. func (*InstallReleaseResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{38} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{43} } func (x *InstallReleaseResponse) GetSuccess() bool { @@ -2844,7 +3193,7 @@ type BooleanResponse struct { func (x *BooleanResponse) Reset() { *x = BooleanResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[39] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2857,7 +3206,7 @@ func (x *BooleanResponse) String() string { func (*BooleanResponse) ProtoMessage() {} func (x *BooleanResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[39] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2870,7 +3219,7 @@ func (x *BooleanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BooleanResponse.ProtoReflect.Descriptor instead. func (*BooleanResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{39} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{44} } func (x *BooleanResponse) GetResult() bool { @@ -2892,7 +3241,7 @@ type RollbackReleaseRequest struct { func (x *RollbackReleaseRequest) Reset() { *x = RollbackReleaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[40] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2905,7 +3254,7 @@ func (x *RollbackReleaseRequest) String() string { func (*RollbackReleaseRequest) ProtoMessage() {} func (x *RollbackReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[40] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2918,7 +3267,7 @@ func (x *RollbackReleaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RollbackReleaseRequest.ProtoReflect.Descriptor instead. func (*RollbackReleaseRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{40} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{45} } func (x *RollbackReleaseRequest) GetReleaseIdentifier() *ReleaseIdentifier { @@ -2947,7 +3296,7 @@ type TemplateChartResponse struct { func (x *TemplateChartResponse) Reset() { *x = TemplateChartResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[41] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2960,7 +3309,7 @@ func (x *TemplateChartResponse) String() string { func (*TemplateChartResponse) ProtoMessage() {} func (x *TemplateChartResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[41] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2973,7 +3322,7 @@ func (x *TemplateChartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TemplateChartResponse.ProtoReflect.Descriptor instead. func (*TemplateChartResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{41} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{46} } func (x *TemplateChartResponse) GetGeneratedManifest() string { @@ -3001,7 +3350,7 @@ type BulkTemplateChartResponse struct { func (x *BulkTemplateChartResponse) Reset() { *x = BulkTemplateChartResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[42] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3014,7 +3363,7 @@ func (x *BulkTemplateChartResponse) String() string { func (*BulkTemplateChartResponse) ProtoMessage() {} func (x *BulkTemplateChartResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[42] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3027,7 +3376,7 @@ func (x *BulkTemplateChartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BulkTemplateChartResponse.ProtoReflect.Descriptor instead. func (*BulkTemplateChartResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{42} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{47} } func (x *BulkTemplateChartResponse) GetBulkTemplateChartResponse() []*TemplateChartResponse { @@ -3052,7 +3401,7 @@ type HelmInstallCustomRequest struct { func (x *HelmInstallCustomRequest) Reset() { *x = HelmInstallCustomRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[43] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3065,7 +3414,7 @@ func (x *HelmInstallCustomRequest) String() string { func (*HelmInstallCustomRequest) ProtoMessage() {} func (x *HelmInstallCustomRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[43] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3078,7 +3427,7 @@ func (x *HelmInstallCustomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HelmInstallCustomRequest.ProtoReflect.Descriptor instead. func (*HelmInstallCustomRequest) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{43} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{48} } func (x *HelmInstallCustomRequest) GetValuesYaml() string { @@ -3127,7 +3476,7 @@ type HelmInstallCustomResponse struct { func (x *HelmInstallCustomResponse) Reset() { *x = HelmInstallCustomResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[44] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3140,7 +3489,7 @@ func (x *HelmInstallCustomResponse) String() string { func (*HelmInstallCustomResponse) ProtoMessage() {} func (x *HelmInstallCustomResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[44] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3153,7 +3502,7 @@ func (x *HelmInstallCustomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HelmInstallCustomResponse.ProtoReflect.Descriptor instead. func (*HelmInstallCustomResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{44} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{49} } func (x *HelmInstallCustomResponse) GetSuccess() bool { @@ -3174,7 +3523,7 @@ type ChartContent struct { func (x *ChartContent) Reset() { *x = ChartContent{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[45] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3187,7 +3536,7 @@ func (x *ChartContent) String() string { func (*ChartContent) ProtoMessage() {} func (x *ChartContent) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[45] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3200,7 +3549,7 @@ func (x *ChartContent) ProtoReflect() protoreflect.Message { // Deprecated: Use ChartContent.ProtoReflect.Descriptor instead. func (*ChartContent) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{45} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{50} } func (x *ChartContent) GetContent() []byte { @@ -3223,7 +3572,7 @@ type Gvk struct { func (x *Gvk) Reset() { *x = Gvk{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[46] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3236,7 +3585,7 @@ func (x *Gvk) String() string { func (*Gvk) ProtoMessage() {} func (x *Gvk) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[46] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3249,7 +3598,7 @@ func (x *Gvk) ProtoReflect() protoreflect.Message { // Deprecated: Use Gvk.ProtoReflect.Descriptor instead. func (*Gvk) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{46} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{51} } func (x *Gvk) GetGroup() string { @@ -3285,7 +3634,7 @@ type ResourceFilter struct { func (x *ResourceFilter) Reset() { *x = ResourceFilter{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[47] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3298,7 +3647,7 @@ func (x *ResourceFilter) String() string { func (*ResourceFilter) ProtoMessage() {} func (x *ResourceFilter) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[47] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3311,7 +3660,7 @@ func (x *ResourceFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceFilter.ProtoReflect.Descriptor instead. func (*ResourceFilter) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{47} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{52} } func (x *ResourceFilter) GetGvk() *Gvk { @@ -3339,7 +3688,7 @@ type ResourceIdentifier struct { func (x *ResourceIdentifier) Reset() { *x = ResourceIdentifier{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[48] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3352,7 +3701,7 @@ func (x *ResourceIdentifier) String() string { func (*ResourceIdentifier) ProtoMessage() {} func (x *ResourceIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[48] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3365,7 +3714,7 @@ func (x *ResourceIdentifier) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceIdentifier.ProtoReflect.Descriptor instead. func (*ResourceIdentifier) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{48} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{53} } func (x *ResourceIdentifier) GetLabels() map[string]string { @@ -3387,7 +3736,7 @@ type ResourceTreeFilter struct { func (x *ResourceTreeFilter) Reset() { *x = ResourceTreeFilter{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[49] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3400,7 +3749,7 @@ func (x *ResourceTreeFilter) String() string { func (*ResourceTreeFilter) ProtoMessage() {} func (x *ResourceTreeFilter) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[49] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3413,7 +3762,7 @@ func (x *ResourceTreeFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceTreeFilter.ProtoReflect.Descriptor instead. func (*ResourceTreeFilter) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{49} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{54} } func (x *ResourceTreeFilter) GetGlobalFilter() *ResourceIdentifier { @@ -3441,7 +3790,7 @@ type ChartNotesResponse struct { func (x *ChartNotesResponse) Reset() { *x = ChartNotesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[50] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3454,7 +3803,7 @@ func (x *ChartNotesResponse) String() string { func (*ChartNotesResponse) ProtoMessage() {} func (x *ChartNotesResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[50] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3467,7 +3816,7 @@ func (x *ChartNotesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChartNotesResponse.ProtoReflect.Descriptor instead. func (*ChartNotesResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{50} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{55} } func (x *ChartNotesResponse) GetNotes() string { @@ -3500,7 +3849,7 @@ type RegistryCredential struct { func (x *RegistryCredential) Reset() { *x = RegistryCredential{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[51] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3513,7 +3862,7 @@ func (x *RegistryCredential) String() string { func (*RegistryCredential) ProtoMessage() {} func (x *RegistryCredential) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[51] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3526,7 +3875,7 @@ func (x *RegistryCredential) ProtoReflect() protoreflect.Message { // Deprecated: Use RegistryCredential.ProtoReflect.Descriptor instead. func (*RegistryCredential) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{51} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{56} } func (x *RegistryCredential) GetRegistryUrl() string { @@ -3633,7 +3982,7 @@ type RemoteConnectionConfig struct { func (x *RemoteConnectionConfig) Reset() { *x = RemoteConnectionConfig{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[52] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3646,7 +3995,7 @@ func (x *RemoteConnectionConfig) String() string { func (*RemoteConnectionConfig) ProtoMessage() {} func (x *RemoteConnectionConfig) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[52] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3659,7 +4008,7 @@ func (x *RemoteConnectionConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoteConnectionConfig.ProtoReflect.Descriptor instead. func (*RemoteConnectionConfig) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{52} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{57} } func (x *RemoteConnectionConfig) GetRemoteConnectionMethod() RemoteConnectionMethod { @@ -3694,7 +4043,7 @@ type ProxyConfig struct { func (x *ProxyConfig) Reset() { *x = ProxyConfig{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[53] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3707,7 +4056,7 @@ func (x *ProxyConfig) String() string { func (*ProxyConfig) ProtoMessage() {} func (x *ProxyConfig) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[53] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3720,7 +4069,7 @@ func (x *ProxyConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ProxyConfig.ProtoReflect.Descriptor instead. func (*ProxyConfig) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{53} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{58} } func (x *ProxyConfig) GetProxyUrl() string { @@ -3744,7 +4093,7 @@ type SSHTunnelConfig struct { func (x *SSHTunnelConfig) Reset() { *x = SSHTunnelConfig{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[54] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3757,7 +4106,7 @@ func (x *SSHTunnelConfig) String() string { func (*SSHTunnelConfig) ProtoMessage() {} func (x *SSHTunnelConfig) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[54] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3770,7 +4119,7 @@ func (x *SSHTunnelConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use SSHTunnelConfig.ProtoReflect.Descriptor instead. func (*SSHTunnelConfig) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{54} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{59} } func (x *SSHTunnelConfig) GetSSHServerAddress() string { @@ -3812,7 +4161,7 @@ type OCIRegistryResponse struct { func (x *OCIRegistryResponse) Reset() { *x = OCIRegistryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[55] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3825,7 +4174,7 @@ func (x *OCIRegistryResponse) String() string { func (*OCIRegistryResponse) ProtoMessage() {} func (x *OCIRegistryResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[55] + mi := &file_api_helm_app_gRPC_applist_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3838,7 +4187,7 @@ func (x *OCIRegistryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use OCIRegistryResponse.ProtoReflect.Descriptor instead. func (*OCIRegistryResponse) Descriptor() ([]byte, []int) { - return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{55} + return file_api_helm_app_gRPC_applist_proto_rawDescGZIP(), []int{60} } func (x *OCIRegistryResponse) GetIsLoggedIn() bool { @@ -3895,626 +4244,689 @@ var file_api_helm_app_gRPC_applist_proto_rawDesc = []byte{ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1c, - 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x65, 0x64, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, - 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, - 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x72, 0x74, 0x41, - 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, - 0x72, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x41, 0x0a, 0x11, 0x65, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x11, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, - 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x4c, - 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x63, - 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0x72, 0x0a, 0x12, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x22, 0xcd, 0x01, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, - 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x43, - 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x22, 0x99, 0x03, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x34, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3e, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, - 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, - 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x14, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x22, - 0xc1, 0x01, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, - 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x13, 0x46, 0x6c, 0x75, + 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3a, + 0x0a, 0x0f, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x46, 0x6c, 0x75, 0x78, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, + 0x22, 0xe2, 0x01, 0x0a, 0x0f, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x73, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x41, 0x0a, 0x11, + 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x11, 0x65, 0x6e, + 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, + 0x34, 0x0a, 0x15, 0x66, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, + 0x66, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, + 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, + 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x49, 0x73, 0x4b, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x49, 0x73, 0x4b, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x22, 0xde, + 0x01, 0x0a, 0x0d, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x12, 0x3a, 0x0a, 0x0f, 0x66, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x46, 0x6c, 0x75, 0x78, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x66, 0x6c, 0x75, + 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x13, + 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x46, 0x6c, 0x75, 0x78, + 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, + 0x13, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x12, 0x49, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x5f, 0x0a, 0x13, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0xa7, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, + 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x52, 0x11, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x72, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x72, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, + 0x12, 0x41, 0x0a, 0x11, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x45, 0x6e, + 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x52, 0x11, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x65, 0x64, 0x22, 0x63, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb7, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, - 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, - 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x68, 0x6f, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, - 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, - 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, - 0x2e, 0x0a, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, - 0xa9, 0x04, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x25, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x73, 0x48, 0x69, - 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, - 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0f, - 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, 0x65, - 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x49, 0x74, 0x65, 0x6d, 0x52, - 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x03, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x48, 0x6f, 0x6f, - 0x6b, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x48, 0x6f, 0x6f, 0x6b, 0x12, - 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x6f, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x68, 0x6f, 0x6f, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x22, 0x34, 0x0a, 0x08, 0x49, - 0x6e, 0x66, 0x6f, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x40, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3b, - 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x95, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0xdc, - 0x01, 0x0a, 0x0b, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x73, 0x4e, 0x65, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x73, 0x4e, - 0x65, 0x77, 0x12, 0x49, 0x0a, 0x13, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x13, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, - 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x4c, 0x0a, - 0x16, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, - 0x73, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x87, 0x01, 0x0a, 0x10, - 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x79, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x72, 0x0a, 0x12, 0x45, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x20, 0x0a, + 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1c, 0x0a, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xcd, 0x01, 0x0a, 0x10, + 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x10, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x22, 0x7e, 0x0a, 0x0f, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0c, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, - 0x22, 0x3d, 0x0a, 0x11, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x81, 0x02, 0x0a, 0x17, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x63, - 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x3a, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x43, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, + 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x99, 0x03, 0x0a, 0x09, + 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0d, + 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3e, 0x0a, + 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x42, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x42, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x62, 0x0a, 0x18, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, - 0x46, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x48, 0x65, 0x6c, - 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x85, 0x02, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x40, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, - 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, - 0x26, 0x0a, 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, - 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, - 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x64, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x22, - 0xd2, 0x01, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x12, 0x34, 0x0a, + 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, + 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, + 0x0a, 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x45, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, + 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x45, 0x78, + 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x22, 0xc1, 0x01, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, + 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x4c, + 0x61, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x22, 0x63, 0x0a, 0x0d, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0xb7, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x14, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, + 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x70, 0x6f, 0x64, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa9, 0x04, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, + 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, + 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x66, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x3f, + 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x06, 0x68, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, + 0x61, 0x74, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, + 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1d, + 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x49, + 0x6e, 0x66, 0x6f, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x6f, 0x72, 0x74, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x03, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x69, 0x73, 0x48, 0x6f, 0x6f, 0x6b, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x69, 0x73, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x6f, 0x6b, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x6f, 0x6b, 0x54, + 0x79, 0x70, 0x65, 0x22, 0x34, 0x0a, 0x08, 0x49, 0x6e, 0x66, 0x6f, 0x49, 0x74, 0x65, 0x6d, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x40, 0x0a, 0x0c, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x16, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x2e, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x95, + 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x12, 0x14, + 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0xdc, 0x01, 0x0a, 0x0b, 0x50, 0x6f, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, + 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x73, 0x4e, 0x65, 0x77, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x73, 0x4e, 0x65, 0x77, 0x12, 0x49, 0x0a, 0x13, 0x65, 0x70, + 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, + 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x13, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x4c, 0x0a, 0x16, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, + 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x22, 0x87, 0x01, 0x0a, 0x10, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, + 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x88, 0x01, + 0x0a, 0x10, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x7e, 0x0a, 0x0f, 0x48, 0x69, 0x62, 0x65, + 0x72, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x22, 0x35, 0x0a, 0x17, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, - 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x18, 0x55, - 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x22, 0x97, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, - 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x88, 0x02, 0x0a, 0x15, - 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x4d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x68, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, - 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x75, - 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x52, 0x75, - 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x16, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x18, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x1e, - 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0xa9, - 0x01, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x12, 0x38, 0x0a, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, - 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x04, 0x0a, 0x15, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x3a, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, - 0x61, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x79, 0x4d, 0x61, 0x78, 0x12, 0x43, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x73, 0x4f, - 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x49, 0x73, - 0x4f, 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x3e, 0x0a, 0x1a, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1a, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, - 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, - 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x71, 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x54, 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x19, 0x42, 0x75, - 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x32, 0x0a, 0x16, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x0f, 0x42, - 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x74, 0x0a, 0x16, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, - 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, - 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5f, 0x0a, 0x15, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x71, 0x0a, - 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x19, 0x42, 0x75, - 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0xeb, 0x01, 0x0a, 0x18, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, - 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x31, 0x0a, - 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, + 0x66, 0x69, 0x65, 0x72, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x22, 0x3d, 0x0a, 0x11, 0x48, 0x69, 0x62, 0x65, + 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x81, 0x02, 0x0a, 0x17, 0x48, 0x65, 0x6c, 0x6d, + 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x68, 0x61, + 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x72, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x6f, 0x63, + 0x6b, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x42, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, + 0x64, 0x42, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x62, 0x0a, 0x18, 0x48, + 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, + 0x85, 0x02, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x40, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, + 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, + 0x22, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x20, + 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x35, 0x0a, 0x17, + 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x18, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x11, 0x52, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, + 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x22, 0x88, 0x02, 0x0a, 0x15, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x18, 0x04, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, + 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, + 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x12, + 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x12, 0x1e, - 0x0a, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x35, - 0x0a, 0x19, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, - 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x28, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, - 0x49, 0x0a, 0x03, 0x47, 0x76, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x22, 0x6d, 0x0a, 0x0e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x03, - 0x67, 0x76, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x47, 0x76, 0x6b, 0x52, - 0x03, 0x67, 0x76, 0x6b, 0x12, 0x43, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x12, 0x37, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0c, 0x67, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0c, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, - 0x2a, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x22, 0xeb, 0x03, 0x0a, 0x12, + 0x0a, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x32, + 0x0a, 0x16, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, + 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x12, 0x2c, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x64, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, + 0x0a, 0x18, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0xa9, 0x01, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x38, 0x0a, 0x17, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0xa7, 0x04, 0x0a, 0x15, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, + 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1c, + 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, + 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, + 0x12, 0x3a, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x68, 0x61, + 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, + 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, + 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x43, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, - 0x41, 0x77, 0x73, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x41, 0x77, 0x73, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x63, - 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, - 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, - 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x73, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x49, 0x73, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x12, 0x4f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x52, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x16, 0x52, 0x65, + 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x12, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x73, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x49, 0x73, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x12, + 0x3e, 0x0a, 0x1a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x1a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, + 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x71, 0x0a, 0x19, + 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x19, 0x42, 0x75, 0x6c, + 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x32, 0x0a, 0x16, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x0f, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x74, + 0x0a, 0x16, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5f, 0x0a, 0x15, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, + 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, + 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x71, 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x54, 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x19, 0x42, + 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xeb, 0x01, 0x0a, 0x18, 0x48, 0x65, 0x6c, + 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, + 0x61, 0x6d, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x43, 0x68, + 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x75, + 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x52, 0x75, + 0x6e, 0x49, 0x6e, 0x43, 0x74, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x4b, 0x38, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4b, 0x38, 0x73, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x35, 0x0a, 0x19, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x28, 0x0a, + 0x0c, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x49, 0x0a, 0x03, 0x47, 0x76, 0x6b, 0x12, 0x14, + 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, + 0x6e, 0x64, 0x22, 0x6d, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x03, 0x67, 0x76, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x04, 0x2e, 0x47, 0x76, 0x6b, 0x52, 0x03, 0x67, 0x76, 0x6b, 0x12, 0x43, 0x0a, 0x12, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x12, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x01, 0x0a, + 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0c, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0c, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, + 0x74, 0x65, 0x73, 0x22, 0xeb, 0x03, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, + 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x77, 0x73, 0x52, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x77, 0x73, 0x52, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, + 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x22, + 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x49, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x49, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x4f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x16, 0x52, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x30, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x16, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2e, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, - 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x0f, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x22, 0x29, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x22, 0xa1, 0x01, 0x0a, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2e, 0x0a, + 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x53, 0x48, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x53, 0x53, 0x48, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, - 0x53, 0x53, 0x48, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x53, 0x53, 0x48, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x53, 0x53, 0x48, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x53, 0x48, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, - 0x22, 0x35, 0x0a, 0x13, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x73, 0x4c, 0x6f, 0x67, - 0x67, 0x65, 0x64, 0x49, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x49, 0x73, 0x4c, - 0x6f, 0x67, 0x67, 0x65, 0x64, 0x49, 0x6e, 0x2a, 0x38, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, - 0x53, 0x53, 0x48, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, - 0x02, 0x32, 0xe7, 0x0b, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0f, 0x2e, 0x41, - 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x22, - 0x00, 0x30, 0x01, 0x12, 0x2f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, - 0x61, 0x69, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0a, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0a, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, - 0x74, 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0b, 0x55, - 0x6e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, - 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, - 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x11, 0x2e, 0x41, 0x70, - 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x11, 0x2e, 0x41, - 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x0c, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, - 0x40, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, - 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x43, 0x0a, 0x10, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x19, 0x2e, 0x55, 0x6e, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, + 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x29, 0x0a, 0x0b, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x55, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x55, 0x72, 0x6c, 0x22, 0xa1, 0x01, 0x0a, 0x0f, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x53, 0x48, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x10, 0x53, 0x53, 0x48, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x53, 0x48, 0x55, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x53, 0x48, 0x55, 0x73, + 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x53, 0x48, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x53, 0x48, + 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x53, 0x48, 0x41, + 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x53, + 0x48, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x22, 0x35, 0x0a, 0x13, 0x4f, 0x43, 0x49, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x49, 0x73, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x49, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x49, 0x73, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x49, 0x6e, 0x2a, + 0x38, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, + 0x58, 0x59, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x01, 0x12, 0x0a, 0x0a, + 0x06, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x32, 0xe7, 0x0c, 0x0a, 0x12, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x39, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0f, 0x2e, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, + 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x0f, 0x2e, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2f, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x11, + 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0a, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x00, 0x12, + 0x2f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x0a, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x00, + 0x12, 0x34, 0x0a, 0x09, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, + 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x12, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0b, 0x55, 0x6e, 0x48, 0x69, 0x62, 0x65, + 0x72, 0x6e, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, + 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, + 0x0a, 0x14, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x48, 0x65, 0x6c, 0x6d, + 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x12, 0x47, 0x65, + 0x74, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x10, + 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x1a, 0x19, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, + 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x18, 0x2e, + 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x1b, 0x55, 0x70, 0x67, + 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x43, + 0x68, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x12, 0x18, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, - 0x0a, 0x1b, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x57, 0x69, 0x74, 0x68, 0x43, 0x68, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x3c, 0x0a, 0x12, 0x49, 0x73, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, - 0x0a, 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x12, 0x17, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, - 0x0a, 0x0d, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x12, - 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x4d, 0x0a, 0x11, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, - 0x72, 0x74, 0x42, 0x75, 0x6c, 0x6b, 0x12, 0x1a, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x12, 0x49, + 0x73, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, + 0x64, 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0f, 0x52, 0x6f, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x17, 0x2e, 0x52, + 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0d, 0x54, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x58, 0x0a, 0x1d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x72, - 0x74, 0x12, 0x19, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x48, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, + 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x11, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, 0x74, 0x42, 0x75, 0x6c, + 0x6b, 0x12, 0x1a, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x1d, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, + 0x68, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x47, 0x65, - 0x74, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, - 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x1d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x43, 0x68, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x13, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x12, 0x13, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x1a, 0x14, 0x2e, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, - 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, - 0x46, 0x6f, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x76, 0x74, 0x72, 0x6f, - 0x6e, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, - 0x62, 0x65, 0x61, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x52, 0x50, 0x43, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x65, + 0x73, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x52, 0x0a, 0x1d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x12, 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x13, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x4f, 0x43, 0x49, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x12, 0x13, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x1a, 0x14, 0x2e, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x46, 0x6f, 0x72, 0x45, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, + 0x1c, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x46, 0x6c, 0x75, + 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x15, 0x2e, 0x46, 0x6c, 0x75, + 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0e, 0x2e, 0x46, 0x6c, 0x75, 0x78, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x22, 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x64, 0x65, 0x76, 0x74, 0x72, 0x6f, 0x6e, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6b, + 0x75, 0x62, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x62, 0x65, 0x61, 0x6e, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x67, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4530,173 +4942,188 @@ func file_api_helm_app_gRPC_applist_proto_rawDescGZIP() []byte { } var file_api_helm_app_gRPC_applist_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_api_helm_app_gRPC_applist_proto_msgTypes = make([]protoimpl.MessageInfo, 58) -var file_api_helm_app_gRPC_applist_proto_goTypes = []interface{}{ +var file_api_helm_app_gRPC_applist_proto_msgTypes = make([]protoimpl.MessageInfo, 63) +var file_api_helm_app_gRPC_applist_proto_goTypes = []any{ (RemoteConnectionMethod)(0), // 0: RemoteConnectionMethod (*ClusterConfig)(nil), // 1: ClusterConfig (*AppListRequest)(nil), // 2: AppListRequest (*ExternalResourceTreeRequest)(nil), // 3: ExternalResourceTreeRequest (*ExternalResourceDetail)(nil), // 4: ExternalResourceDetail - (*DeployedAppList)(nil), // 5: DeployedAppList - (*DeployedAppDetail)(nil), // 6: DeployedAppDetail - (*EnvironmentDetails)(nil), // 7: EnvironmentDetails - (*AppDetailRequest)(nil), // 8: AppDetailRequest - (*AppDetail)(nil), // 9: AppDetail - (*AppStatus)(nil), // 10: AppStatus - (*ReleaseStatus)(nil), // 11: ReleaseStatus - (*ChartMetadata)(nil), // 12: ChartMetadata - (*ResourceTreeResponse)(nil), // 13: ResourceTreeResponse - (*ResourceNode)(nil), // 14: ResourceNode - (*InfoItem)(nil), // 15: InfoItem - (*HealthStatus)(nil), // 16: HealthStatus - (*ResourceNetworkingInfo)(nil), // 17: ResourceNetworkingInfo - (*ResourceRef)(nil), // 18: ResourceRef - (*PodMetadata)(nil), // 19: PodMetadata - (*EphemeralContainerData)(nil), // 20: EphemeralContainerData - (*HibernateRequest)(nil), // 21: HibernateRequest - (*ObjectIdentifier)(nil), // 22: ObjectIdentifier - (*HibernateStatus)(nil), // 23: HibernateStatus - (*HibernateResponse)(nil), // 24: HibernateResponse - (*HelmAppDeploymentDetail)(nil), // 25: HelmAppDeploymentDetail - (*HelmAppDeploymentHistory)(nil), // 26: HelmAppDeploymentHistory - (*ReleaseInfo)(nil), // 27: ReleaseInfo - (*ObjectRequest)(nil), // 28: ObjectRequest - (*DesiredManifestResponse)(nil), // 29: DesiredManifestResponse - (*UninstallReleaseResponse)(nil), // 30: UninstallReleaseResponse - (*ReleaseIdentifier)(nil), // 31: ReleaseIdentifier - (*UpgradeReleaseRequest)(nil), // 32: UpgradeReleaseRequest - (*UpgradeReleaseResponse)(nil), // 33: UpgradeReleaseResponse - (*DeploymentDetailRequest)(nil), // 34: DeploymentDetailRequest - (*DeploymentDetailResponse)(nil), // 35: DeploymentDetailResponse - (*ChartRepository)(nil), // 36: ChartRepository - (*InstallReleaseRequest)(nil), // 37: InstallReleaseRequest - (*BulkInstallReleaseRequest)(nil), // 38: BulkInstallReleaseRequest - (*InstallReleaseResponse)(nil), // 39: InstallReleaseResponse - (*BooleanResponse)(nil), // 40: BooleanResponse - (*RollbackReleaseRequest)(nil), // 41: RollbackReleaseRequest - (*TemplateChartResponse)(nil), // 42: TemplateChartResponse - (*BulkTemplateChartResponse)(nil), // 43: BulkTemplateChartResponse - (*HelmInstallCustomRequest)(nil), // 44: HelmInstallCustomRequest - (*HelmInstallCustomResponse)(nil), // 45: HelmInstallCustomResponse - (*ChartContent)(nil), // 46: ChartContent - (*Gvk)(nil), // 47: Gvk - (*ResourceFilter)(nil), // 48: ResourceFilter - (*ResourceIdentifier)(nil), // 49: ResourceIdentifier - (*ResourceTreeFilter)(nil), // 50: ResourceTreeFilter - (*ChartNotesResponse)(nil), // 51: ChartNotesResponse - (*RegistryCredential)(nil), // 52: RegistryCredential - (*RemoteConnectionConfig)(nil), // 53: RemoteConnectionConfig - (*ProxyConfig)(nil), // 54: ProxyConfig - (*SSHTunnelConfig)(nil), // 55: SSHTunnelConfig - (*OCIRegistryResponse)(nil), // 56: OCIRegistryResponse - nil, // 57: ResourceNetworkingInfo.LabelsEntry - nil, // 58: ResourceIdentifier.LabelsEntry - (*timestamp.Timestamp)(nil), // 59: google.protobuf.Timestamp + (*FluxApplicationList)(nil), // 5: FluxApplicationList + (*FluxApplication)(nil), // 6: FluxApplication + (*FluxAppDetailRequest)(nil), // 7: FluxAppDetailRequest + (*FluxAppDetail)(nil), // 8: FluxAppDetail + (*FluxAppStatusDetail)(nil), // 9: FluxAppStatusDetail + (*DeployedAppList)(nil), // 10: DeployedAppList + (*DeployedAppDetail)(nil), // 11: DeployedAppDetail + (*EnvironmentDetails)(nil), // 12: EnvironmentDetails + (*AppDetailRequest)(nil), // 13: AppDetailRequest + (*AppDetail)(nil), // 14: AppDetail + (*AppStatus)(nil), // 15: AppStatus + (*ReleaseStatus)(nil), // 16: ReleaseStatus + (*ChartMetadata)(nil), // 17: ChartMetadata + (*ResourceTreeResponse)(nil), // 18: ResourceTreeResponse + (*ResourceNode)(nil), // 19: ResourceNode + (*InfoItem)(nil), // 20: InfoItem + (*HealthStatus)(nil), // 21: HealthStatus + (*ResourceNetworkingInfo)(nil), // 22: ResourceNetworkingInfo + (*ResourceRef)(nil), // 23: ResourceRef + (*PodMetadata)(nil), // 24: PodMetadata + (*EphemeralContainerData)(nil), // 25: EphemeralContainerData + (*HibernateRequest)(nil), // 26: HibernateRequest + (*ObjectIdentifier)(nil), // 27: ObjectIdentifier + (*HibernateStatus)(nil), // 28: HibernateStatus + (*HibernateResponse)(nil), // 29: HibernateResponse + (*HelmAppDeploymentDetail)(nil), // 30: HelmAppDeploymentDetail + (*HelmAppDeploymentHistory)(nil), // 31: HelmAppDeploymentHistory + (*ReleaseInfo)(nil), // 32: ReleaseInfo + (*ObjectRequest)(nil), // 33: ObjectRequest + (*DesiredManifestResponse)(nil), // 34: DesiredManifestResponse + (*UninstallReleaseResponse)(nil), // 35: UninstallReleaseResponse + (*ReleaseIdentifier)(nil), // 36: ReleaseIdentifier + (*UpgradeReleaseRequest)(nil), // 37: UpgradeReleaseRequest + (*UpgradeReleaseResponse)(nil), // 38: UpgradeReleaseResponse + (*DeploymentDetailRequest)(nil), // 39: DeploymentDetailRequest + (*DeploymentDetailResponse)(nil), // 40: DeploymentDetailResponse + (*ChartRepository)(nil), // 41: ChartRepository + (*InstallReleaseRequest)(nil), // 42: InstallReleaseRequest + (*BulkInstallReleaseRequest)(nil), // 43: BulkInstallReleaseRequest + (*InstallReleaseResponse)(nil), // 44: InstallReleaseResponse + (*BooleanResponse)(nil), // 45: BooleanResponse + (*RollbackReleaseRequest)(nil), // 46: RollbackReleaseRequest + (*TemplateChartResponse)(nil), // 47: TemplateChartResponse + (*BulkTemplateChartResponse)(nil), // 48: BulkTemplateChartResponse + (*HelmInstallCustomRequest)(nil), // 49: HelmInstallCustomRequest + (*HelmInstallCustomResponse)(nil), // 50: HelmInstallCustomResponse + (*ChartContent)(nil), // 51: ChartContent + (*Gvk)(nil), // 52: Gvk + (*ResourceFilter)(nil), // 53: ResourceFilter + (*ResourceIdentifier)(nil), // 54: ResourceIdentifier + (*ResourceTreeFilter)(nil), // 55: ResourceTreeFilter + (*ChartNotesResponse)(nil), // 56: ChartNotesResponse + (*RegistryCredential)(nil), // 57: RegistryCredential + (*RemoteConnectionConfig)(nil), // 58: RemoteConnectionConfig + (*ProxyConfig)(nil), // 59: ProxyConfig + (*SSHTunnelConfig)(nil), // 60: SSHTunnelConfig + (*OCIRegistryResponse)(nil), // 61: OCIRegistryResponse + nil, // 62: ResourceNetworkingInfo.LabelsEntry + nil, // 63: ResourceIdentifier.LabelsEntry + (*timestamp.Timestamp)(nil), // 64: google.protobuf.Timestamp } var file_api_helm_app_gRPC_applist_proto_depIdxs = []int32{ 1, // 0: AppListRequest.clusters:type_name -> ClusterConfig 1, // 1: ExternalResourceTreeRequest.clusterConfig:type_name -> ClusterConfig 4, // 2: ExternalResourceTreeRequest.externalResourceDetail:type_name -> ExternalResourceDetail - 6, // 3: DeployedAppList.DeployedAppDetail:type_name -> DeployedAppDetail - 7, // 4: DeployedAppDetail.environmentDetail:type_name -> EnvironmentDetails - 59, // 5: DeployedAppDetail.LastDeployed:type_name -> google.protobuf.Timestamp - 1, // 6: AppDetailRequest.clusterConfig:type_name -> ClusterConfig - 50, // 7: AppDetailRequest.resourceTreeFilter:type_name -> ResourceTreeFilter - 11, // 8: AppDetail.releaseStatus:type_name -> ReleaseStatus - 59, // 9: AppDetail.lastDeployed:type_name -> google.protobuf.Timestamp - 12, // 10: AppDetail.chartMetadata:type_name -> ChartMetadata - 13, // 11: AppDetail.resourceTreeResponse:type_name -> ResourceTreeResponse - 7, // 12: AppDetail.environmentDetails:type_name -> EnvironmentDetails - 59, // 13: AppStatus.LastDeployed:type_name -> google.protobuf.Timestamp - 14, // 14: ResourceTreeResponse.nodes:type_name -> ResourceNode - 19, // 15: ResourceTreeResponse.podMetadata:type_name -> PodMetadata - 18, // 16: ResourceNode.parentRefs:type_name -> ResourceRef - 17, // 17: ResourceNode.networkingInfo:type_name -> ResourceNetworkingInfo - 16, // 18: ResourceNode.health:type_name -> HealthStatus - 15, // 19: ResourceNode.info:type_name -> InfoItem - 57, // 20: ResourceNetworkingInfo.labels:type_name -> ResourceNetworkingInfo.LabelsEntry - 20, // 21: PodMetadata.ephemeralContainers:type_name -> EphemeralContainerData - 1, // 22: HibernateRequest.clusterConfig:type_name -> ClusterConfig - 22, // 23: HibernateRequest.objectIdentifier:type_name -> ObjectIdentifier - 22, // 24: HibernateStatus.targetObject:type_name -> ObjectIdentifier - 23, // 25: HibernateResponse.status:type_name -> HibernateStatus - 12, // 26: HelmAppDeploymentDetail.chartMetadata:type_name -> ChartMetadata - 59, // 27: HelmAppDeploymentDetail.deployedAt:type_name -> google.protobuf.Timestamp - 25, // 28: HelmAppDeploymentHistory.deploymentHistory:type_name -> HelmAppDeploymentDetail - 6, // 29: ReleaseInfo.deployedAppDetail:type_name -> DeployedAppDetail - 1, // 30: ObjectRequest.clusterConfig:type_name -> ClusterConfig - 22, // 31: ObjectRequest.objectIdentifier:type_name -> ObjectIdentifier - 1, // 32: ReleaseIdentifier.clusterConfig:type_name -> ClusterConfig - 31, // 33: UpgradeReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier - 46, // 34: UpgradeReleaseRequest.chartContent:type_name -> ChartContent - 31, // 35: DeploymentDetailRequest.releaseIdentifier:type_name -> ReleaseIdentifier - 31, // 36: InstallReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier - 36, // 37: InstallReleaseRequest.chartRepository:type_name -> ChartRepository - 52, // 38: InstallReleaseRequest.RegistryCredential:type_name -> RegistryCredential - 46, // 39: InstallReleaseRequest.chartContent:type_name -> ChartContent - 37, // 40: BulkInstallReleaseRequest.BulkInstallReleaseRequest:type_name -> InstallReleaseRequest - 31, // 41: RollbackReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier - 42, // 42: BulkTemplateChartResponse.BulkTemplateChartResponse:type_name -> TemplateChartResponse - 46, // 43: HelmInstallCustomRequest.chartContent:type_name -> ChartContent - 31, // 44: HelmInstallCustomRequest.releaseIdentifier:type_name -> ReleaseIdentifier - 47, // 45: ResourceFilter.gvk:type_name -> Gvk - 49, // 46: ResourceFilter.resourceIdentifier:type_name -> ResourceIdentifier - 58, // 47: ResourceIdentifier.labels:type_name -> ResourceIdentifier.LabelsEntry - 49, // 48: ResourceTreeFilter.globalFilter:type_name -> ResourceIdentifier - 48, // 49: ResourceTreeFilter.resourceFilters:type_name -> ResourceFilter - 53, // 50: RegistryCredential.RemoteConnectionConfig:type_name -> RemoteConnectionConfig - 0, // 51: RemoteConnectionConfig.RemoteConnectionMethod:type_name -> RemoteConnectionMethod - 54, // 52: RemoteConnectionConfig.ProxyConfig:type_name -> ProxyConfig - 55, // 53: RemoteConnectionConfig.SSHTunnelConfig:type_name -> SSHTunnelConfig - 2, // 54: ApplicationService.ListApplications:input_type -> AppListRequest - 8, // 55: ApplicationService.GetAppDetail:input_type -> AppDetailRequest - 8, // 56: ApplicationService.GetAppStatus:input_type -> AppDetailRequest - 21, // 57: ApplicationService.Hibernate:input_type -> HibernateRequest - 21, // 58: ApplicationService.UnHibernate:input_type -> HibernateRequest - 8, // 59: ApplicationService.GetDeploymentHistory:input_type -> AppDetailRequest - 8, // 60: ApplicationService.GetValuesYaml:input_type -> AppDetailRequest - 28, // 61: ApplicationService.GetDesiredManifest:input_type -> ObjectRequest - 31, // 62: ApplicationService.UninstallRelease:input_type -> ReleaseIdentifier - 32, // 63: ApplicationService.UpgradeRelease:input_type -> UpgradeReleaseRequest - 34, // 64: ApplicationService.GetDeploymentDetail:input_type -> DeploymentDetailRequest - 37, // 65: ApplicationService.InstallRelease:input_type -> InstallReleaseRequest - 37, // 66: ApplicationService.UpgradeReleaseWithChartInfo:input_type -> InstallReleaseRequest - 31, // 67: ApplicationService.IsReleaseInstalled:input_type -> ReleaseIdentifier - 41, // 68: ApplicationService.RollbackRelease:input_type -> RollbackReleaseRequest - 37, // 69: ApplicationService.TemplateChart:input_type -> InstallReleaseRequest - 38, // 70: ApplicationService.TemplateChartBulk:input_type -> BulkInstallReleaseRequest - 44, // 71: ApplicationService.InstallReleaseWithCustomChart:input_type -> HelmInstallCustomRequest - 37, // 72: ApplicationService.GetNotes:input_type -> InstallReleaseRequest - 32, // 73: ApplicationService.UpgradeReleaseWithCustomChart:input_type -> UpgradeReleaseRequest - 52, // 74: ApplicationService.ValidateOCIRegistry:input_type -> RegistryCredential - 3, // 75: ApplicationService.GetResourceTreeForExternalResources:input_type -> ExternalResourceTreeRequest - 5, // 76: ApplicationService.ListApplications:output_type -> DeployedAppList - 9, // 77: ApplicationService.GetAppDetail:output_type -> AppDetail - 10, // 78: ApplicationService.GetAppStatus:output_type -> AppStatus - 24, // 79: ApplicationService.Hibernate:output_type -> HibernateResponse - 24, // 80: ApplicationService.UnHibernate:output_type -> HibernateResponse - 26, // 81: ApplicationService.GetDeploymentHistory:output_type -> HelmAppDeploymentHistory - 27, // 82: ApplicationService.GetValuesYaml:output_type -> ReleaseInfo - 29, // 83: ApplicationService.GetDesiredManifest:output_type -> DesiredManifestResponse - 30, // 84: ApplicationService.UninstallRelease:output_type -> UninstallReleaseResponse - 33, // 85: ApplicationService.UpgradeRelease:output_type -> UpgradeReleaseResponse - 35, // 86: ApplicationService.GetDeploymentDetail:output_type -> DeploymentDetailResponse - 39, // 87: ApplicationService.InstallRelease:output_type -> InstallReleaseResponse - 33, // 88: ApplicationService.UpgradeReleaseWithChartInfo:output_type -> UpgradeReleaseResponse - 40, // 89: ApplicationService.IsReleaseInstalled:output_type -> BooleanResponse - 40, // 90: ApplicationService.RollbackRelease:output_type -> BooleanResponse - 42, // 91: ApplicationService.TemplateChart:output_type -> TemplateChartResponse - 43, // 92: ApplicationService.TemplateChartBulk:output_type -> BulkTemplateChartResponse - 45, // 93: ApplicationService.InstallReleaseWithCustomChart:output_type -> HelmInstallCustomResponse - 51, // 94: ApplicationService.GetNotes:output_type -> ChartNotesResponse - 33, // 95: ApplicationService.UpgradeReleaseWithCustomChart:output_type -> UpgradeReleaseResponse - 56, // 96: ApplicationService.ValidateOCIRegistry:output_type -> OCIRegistryResponse - 13, // 97: ApplicationService.GetResourceTreeForExternalResources:output_type -> ResourceTreeResponse - 76, // [76:98] is the sub-list for method output_type - 54, // [54:76] is the sub-list for method input_type - 54, // [54:54] is the sub-list for extension type_name - 54, // [54:54] is the sub-list for extension extendee - 0, // [0:54] is the sub-list for field type_name + 6, // 3: FluxApplicationList.FluxApplication:type_name -> FluxApplication + 12, // 4: FluxApplication.environmentDetail:type_name -> EnvironmentDetails + 1, // 5: FluxAppDetailRequest.clusterConfig:type_name -> ClusterConfig + 6, // 6: FluxAppDetail.fluxApplication:type_name -> FluxApplication + 9, // 7: FluxAppDetail.FluxAppStatusDetail:type_name -> FluxAppStatusDetail + 18, // 8: FluxAppDetail.resourceTreeResponse:type_name -> ResourceTreeResponse + 11, // 9: DeployedAppList.DeployedAppDetail:type_name -> DeployedAppDetail + 12, // 10: DeployedAppDetail.environmentDetail:type_name -> EnvironmentDetails + 64, // 11: DeployedAppDetail.LastDeployed:type_name -> google.protobuf.Timestamp + 1, // 12: AppDetailRequest.clusterConfig:type_name -> ClusterConfig + 55, // 13: AppDetailRequest.resourceTreeFilter:type_name -> ResourceTreeFilter + 16, // 14: AppDetail.releaseStatus:type_name -> ReleaseStatus + 64, // 15: AppDetail.lastDeployed:type_name -> google.protobuf.Timestamp + 17, // 16: AppDetail.chartMetadata:type_name -> ChartMetadata + 18, // 17: AppDetail.resourceTreeResponse:type_name -> ResourceTreeResponse + 12, // 18: AppDetail.environmentDetails:type_name -> EnvironmentDetails + 64, // 19: AppStatus.LastDeployed:type_name -> google.protobuf.Timestamp + 19, // 20: ResourceTreeResponse.nodes:type_name -> ResourceNode + 24, // 21: ResourceTreeResponse.podMetadata:type_name -> PodMetadata + 23, // 22: ResourceNode.parentRefs:type_name -> ResourceRef + 22, // 23: ResourceNode.networkingInfo:type_name -> ResourceNetworkingInfo + 21, // 24: ResourceNode.health:type_name -> HealthStatus + 20, // 25: ResourceNode.info:type_name -> InfoItem + 62, // 26: ResourceNetworkingInfo.labels:type_name -> ResourceNetworkingInfo.LabelsEntry + 25, // 27: PodMetadata.ephemeralContainers:type_name -> EphemeralContainerData + 1, // 28: HibernateRequest.clusterConfig:type_name -> ClusterConfig + 27, // 29: HibernateRequest.objectIdentifier:type_name -> ObjectIdentifier + 27, // 30: HibernateStatus.targetObject:type_name -> ObjectIdentifier + 28, // 31: HibernateResponse.status:type_name -> HibernateStatus + 17, // 32: HelmAppDeploymentDetail.chartMetadata:type_name -> ChartMetadata + 64, // 33: HelmAppDeploymentDetail.deployedAt:type_name -> google.protobuf.Timestamp + 30, // 34: HelmAppDeploymentHistory.deploymentHistory:type_name -> HelmAppDeploymentDetail + 11, // 35: ReleaseInfo.deployedAppDetail:type_name -> DeployedAppDetail + 1, // 36: ObjectRequest.clusterConfig:type_name -> ClusterConfig + 27, // 37: ObjectRequest.objectIdentifier:type_name -> ObjectIdentifier + 1, // 38: ReleaseIdentifier.clusterConfig:type_name -> ClusterConfig + 36, // 39: UpgradeReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 51, // 40: UpgradeReleaseRequest.chartContent:type_name -> ChartContent + 36, // 41: DeploymentDetailRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 36, // 42: InstallReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 41, // 43: InstallReleaseRequest.chartRepository:type_name -> ChartRepository + 57, // 44: InstallReleaseRequest.RegistryCredential:type_name -> RegistryCredential + 51, // 45: InstallReleaseRequest.chartContent:type_name -> ChartContent + 42, // 46: BulkInstallReleaseRequest.BulkInstallReleaseRequest:type_name -> InstallReleaseRequest + 36, // 47: RollbackReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 47, // 48: BulkTemplateChartResponse.BulkTemplateChartResponse:type_name -> TemplateChartResponse + 51, // 49: HelmInstallCustomRequest.chartContent:type_name -> ChartContent + 36, // 50: HelmInstallCustomRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 52, // 51: ResourceFilter.gvk:type_name -> Gvk + 54, // 52: ResourceFilter.resourceIdentifier:type_name -> ResourceIdentifier + 63, // 53: ResourceIdentifier.labels:type_name -> ResourceIdentifier.LabelsEntry + 54, // 54: ResourceTreeFilter.globalFilter:type_name -> ResourceIdentifier + 53, // 55: ResourceTreeFilter.resourceFilters:type_name -> ResourceFilter + 58, // 56: RegistryCredential.RemoteConnectionConfig:type_name -> RemoteConnectionConfig + 0, // 57: RemoteConnectionConfig.RemoteConnectionMethod:type_name -> RemoteConnectionMethod + 59, // 58: RemoteConnectionConfig.ProxyConfig:type_name -> ProxyConfig + 60, // 59: RemoteConnectionConfig.SSHTunnelConfig:type_name -> SSHTunnelConfig + 2, // 60: ApplicationService.ListApplications:input_type -> AppListRequest + 2, // 61: ApplicationService.ListFluxApplications:input_type -> AppListRequest + 13, // 62: ApplicationService.GetAppDetail:input_type -> AppDetailRequest + 13, // 63: ApplicationService.GetAppStatus:input_type -> AppDetailRequest + 26, // 64: ApplicationService.Hibernate:input_type -> HibernateRequest + 26, // 65: ApplicationService.UnHibernate:input_type -> HibernateRequest + 13, // 66: ApplicationService.GetDeploymentHistory:input_type -> AppDetailRequest + 13, // 67: ApplicationService.GetValuesYaml:input_type -> AppDetailRequest + 33, // 68: ApplicationService.GetDesiredManifest:input_type -> ObjectRequest + 36, // 69: ApplicationService.UninstallRelease:input_type -> ReleaseIdentifier + 37, // 70: ApplicationService.UpgradeRelease:input_type -> UpgradeReleaseRequest + 39, // 71: ApplicationService.GetDeploymentDetail:input_type -> DeploymentDetailRequest + 42, // 72: ApplicationService.InstallRelease:input_type -> InstallReleaseRequest + 42, // 73: ApplicationService.UpgradeReleaseWithChartInfo:input_type -> InstallReleaseRequest + 36, // 74: ApplicationService.IsReleaseInstalled:input_type -> ReleaseIdentifier + 46, // 75: ApplicationService.RollbackRelease:input_type -> RollbackReleaseRequest + 42, // 76: ApplicationService.TemplateChart:input_type -> InstallReleaseRequest + 43, // 77: ApplicationService.TemplateChartBulk:input_type -> BulkInstallReleaseRequest + 49, // 78: ApplicationService.InstallReleaseWithCustomChart:input_type -> HelmInstallCustomRequest + 42, // 79: ApplicationService.GetNotes:input_type -> InstallReleaseRequest + 37, // 80: ApplicationService.UpgradeReleaseWithCustomChart:input_type -> UpgradeReleaseRequest + 57, // 81: ApplicationService.ValidateOCIRegistry:input_type -> RegistryCredential + 3, // 82: ApplicationService.GetResourceTreeForExternalResources:input_type -> ExternalResourceTreeRequest + 7, // 83: ApplicationService.GetFluxAppDetail:input_type -> FluxAppDetailRequest + 10, // 84: ApplicationService.ListApplications:output_type -> DeployedAppList + 5, // 85: ApplicationService.ListFluxApplications:output_type -> FluxApplicationList + 14, // 86: ApplicationService.GetAppDetail:output_type -> AppDetail + 15, // 87: ApplicationService.GetAppStatus:output_type -> AppStatus + 29, // 88: ApplicationService.Hibernate:output_type -> HibernateResponse + 29, // 89: ApplicationService.UnHibernate:output_type -> HibernateResponse + 31, // 90: ApplicationService.GetDeploymentHistory:output_type -> HelmAppDeploymentHistory + 32, // 91: ApplicationService.GetValuesYaml:output_type -> ReleaseInfo + 34, // 92: ApplicationService.GetDesiredManifest:output_type -> DesiredManifestResponse + 35, // 93: ApplicationService.UninstallRelease:output_type -> UninstallReleaseResponse + 38, // 94: ApplicationService.UpgradeRelease:output_type -> UpgradeReleaseResponse + 40, // 95: ApplicationService.GetDeploymentDetail:output_type -> DeploymentDetailResponse + 44, // 96: ApplicationService.InstallRelease:output_type -> InstallReleaseResponse + 38, // 97: ApplicationService.UpgradeReleaseWithChartInfo:output_type -> UpgradeReleaseResponse + 45, // 98: ApplicationService.IsReleaseInstalled:output_type -> BooleanResponse + 45, // 99: ApplicationService.RollbackRelease:output_type -> BooleanResponse + 47, // 100: ApplicationService.TemplateChart:output_type -> TemplateChartResponse + 48, // 101: ApplicationService.TemplateChartBulk:output_type -> BulkTemplateChartResponse + 50, // 102: ApplicationService.InstallReleaseWithCustomChart:output_type -> HelmInstallCustomResponse + 56, // 103: ApplicationService.GetNotes:output_type -> ChartNotesResponse + 38, // 104: ApplicationService.UpgradeReleaseWithCustomChart:output_type -> UpgradeReleaseResponse + 61, // 105: ApplicationService.ValidateOCIRegistry:output_type -> OCIRegistryResponse + 18, // 106: ApplicationService.GetResourceTreeForExternalResources:output_type -> ResourceTreeResponse + 8, // 107: ApplicationService.GetFluxAppDetail:output_type -> FluxAppDetail + 84, // [84:108] is the sub-list for method output_type + 60, // [60:84] is the sub-list for method input_type + 60, // [60:60] is the sub-list for extension type_name + 60, // [60:60] is the sub-list for extension extendee + 0, // [0:60] is the sub-list for field type_name } func init() { file_api_helm_app_gRPC_applist_proto_init() } @@ -4705,7 +5132,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_api_helm_app_gRPC_applist_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*ClusterConfig); i { case 0: return &v.state @@ -4717,7 +5144,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*AppListRequest); i { case 0: return &v.state @@ -4729,7 +5156,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ExternalResourceTreeRequest); i { case 0: return &v.state @@ -4741,7 +5168,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*ExternalResourceDetail); i { case 0: return &v.state @@ -4753,7 +5180,67 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*FluxApplicationList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_helm_app_gRPC_applist_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*FluxApplication); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_helm_app_gRPC_applist_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*FluxAppDetailRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_helm_app_gRPC_applist_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*FluxAppDetail); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_helm_app_gRPC_applist_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*FluxAppStatusDetail); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_helm_app_gRPC_applist_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*DeployedAppList); i { case 0: return &v.state @@ -4765,7 +5252,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[10].Exporter = func(v any, i int) any { switch v := v.(*DeployedAppDetail); i { case 0: return &v.state @@ -4777,7 +5264,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[11].Exporter = func(v any, i int) any { switch v := v.(*EnvironmentDetails); i { case 0: return &v.state @@ -4789,7 +5276,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[12].Exporter = func(v any, i int) any { switch v := v.(*AppDetailRequest); i { case 0: return &v.state @@ -4801,7 +5288,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[13].Exporter = func(v any, i int) any { switch v := v.(*AppDetail); i { case 0: return &v.state @@ -4813,7 +5300,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[14].Exporter = func(v any, i int) any { switch v := v.(*AppStatus); i { case 0: return &v.state @@ -4825,7 +5312,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[15].Exporter = func(v any, i int) any { switch v := v.(*ReleaseStatus); i { case 0: return &v.state @@ -4837,7 +5324,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[16].Exporter = func(v any, i int) any { switch v := v.(*ChartMetadata); i { case 0: return &v.state @@ -4849,7 +5336,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[17].Exporter = func(v any, i int) any { switch v := v.(*ResourceTreeResponse); i { case 0: return &v.state @@ -4861,7 +5348,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[18].Exporter = func(v any, i int) any { switch v := v.(*ResourceNode); i { case 0: return &v.state @@ -4873,7 +5360,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[19].Exporter = func(v any, i int) any { switch v := v.(*InfoItem); i { case 0: return &v.state @@ -4885,7 +5372,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[20].Exporter = func(v any, i int) any { switch v := v.(*HealthStatus); i { case 0: return &v.state @@ -4897,7 +5384,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[21].Exporter = func(v any, i int) any { switch v := v.(*ResourceNetworkingInfo); i { case 0: return &v.state @@ -4909,7 +5396,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[22].Exporter = func(v any, i int) any { switch v := v.(*ResourceRef); i { case 0: return &v.state @@ -4921,7 +5408,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[23].Exporter = func(v any, i int) any { switch v := v.(*PodMetadata); i { case 0: return &v.state @@ -4933,7 +5420,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[24].Exporter = func(v any, i int) any { switch v := v.(*EphemeralContainerData); i { case 0: return &v.state @@ -4945,7 +5432,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[25].Exporter = func(v any, i int) any { switch v := v.(*HibernateRequest); i { case 0: return &v.state @@ -4957,7 +5444,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[26].Exporter = func(v any, i int) any { switch v := v.(*ObjectIdentifier); i { case 0: return &v.state @@ -4969,7 +5456,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[27].Exporter = func(v any, i int) any { switch v := v.(*HibernateStatus); i { case 0: return &v.state @@ -4981,7 +5468,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[28].Exporter = func(v any, i int) any { switch v := v.(*HibernateResponse); i { case 0: return &v.state @@ -4993,7 +5480,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[29].Exporter = func(v any, i int) any { switch v := v.(*HelmAppDeploymentDetail); i { case 0: return &v.state @@ -5005,7 +5492,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[30].Exporter = func(v any, i int) any { switch v := v.(*HelmAppDeploymentHistory); i { case 0: return &v.state @@ -5017,7 +5504,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[31].Exporter = func(v any, i int) any { switch v := v.(*ReleaseInfo); i { case 0: return &v.state @@ -5029,7 +5516,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[32].Exporter = func(v any, i int) any { switch v := v.(*ObjectRequest); i { case 0: return &v.state @@ -5041,7 +5528,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[33].Exporter = func(v any, i int) any { switch v := v.(*DesiredManifestResponse); i { case 0: return &v.state @@ -5053,7 +5540,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[34].Exporter = func(v any, i int) any { switch v := v.(*UninstallReleaseResponse); i { case 0: return &v.state @@ -5065,7 +5552,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[35].Exporter = func(v any, i int) any { switch v := v.(*ReleaseIdentifier); i { case 0: return &v.state @@ -5077,7 +5564,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[36].Exporter = func(v any, i int) any { switch v := v.(*UpgradeReleaseRequest); i { case 0: return &v.state @@ -5089,7 +5576,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[37].Exporter = func(v any, i int) any { switch v := v.(*UpgradeReleaseResponse); i { case 0: return &v.state @@ -5101,7 +5588,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[38].Exporter = func(v any, i int) any { switch v := v.(*DeploymentDetailRequest); i { case 0: return &v.state @@ -5113,7 +5600,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[39].Exporter = func(v any, i int) any { switch v := v.(*DeploymentDetailResponse); i { case 0: return &v.state @@ -5125,7 +5612,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[40].Exporter = func(v any, i int) any { switch v := v.(*ChartRepository); i { case 0: return &v.state @@ -5137,7 +5624,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[41].Exporter = func(v any, i int) any { switch v := v.(*InstallReleaseRequest); i { case 0: return &v.state @@ -5149,7 +5636,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[42].Exporter = func(v any, i int) any { switch v := v.(*BulkInstallReleaseRequest); i { case 0: return &v.state @@ -5161,7 +5648,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[43].Exporter = func(v any, i int) any { switch v := v.(*InstallReleaseResponse); i { case 0: return &v.state @@ -5173,7 +5660,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[44].Exporter = func(v any, i int) any { switch v := v.(*BooleanResponse); i { case 0: return &v.state @@ -5185,7 +5672,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[45].Exporter = func(v any, i int) any { switch v := v.(*RollbackReleaseRequest); i { case 0: return &v.state @@ -5197,7 +5684,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[46].Exporter = func(v any, i int) any { switch v := v.(*TemplateChartResponse); i { case 0: return &v.state @@ -5209,7 +5696,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[47].Exporter = func(v any, i int) any { switch v := v.(*BulkTemplateChartResponse); i { case 0: return &v.state @@ -5221,7 +5708,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[48].Exporter = func(v any, i int) any { switch v := v.(*HelmInstallCustomRequest); i { case 0: return &v.state @@ -5233,7 +5720,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[49].Exporter = func(v any, i int) any { switch v := v.(*HelmInstallCustomResponse); i { case 0: return &v.state @@ -5245,7 +5732,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[50].Exporter = func(v any, i int) any { switch v := v.(*ChartContent); i { case 0: return &v.state @@ -5257,7 +5744,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[51].Exporter = func(v any, i int) any { switch v := v.(*Gvk); i { case 0: return &v.state @@ -5269,7 +5756,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[52].Exporter = func(v any, i int) any { switch v := v.(*ResourceFilter); i { case 0: return &v.state @@ -5281,7 +5768,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[53].Exporter = func(v any, i int) any { switch v := v.(*ResourceIdentifier); i { case 0: return &v.state @@ -5293,7 +5780,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[54].Exporter = func(v any, i int) any { switch v := v.(*ResourceTreeFilter); i { case 0: return &v.state @@ -5305,7 +5792,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[55].Exporter = func(v any, i int) any { switch v := v.(*ChartNotesResponse); i { case 0: return &v.state @@ -5317,7 +5804,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[56].Exporter = func(v any, i int) any { switch v := v.(*RegistryCredential); i { case 0: return &v.state @@ -5329,7 +5816,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[57].Exporter = func(v any, i int) any { switch v := v.(*RemoteConnectionConfig); i { case 0: return &v.state @@ -5341,7 +5828,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[58].Exporter = func(v any, i int) any { switch v := v.(*ProxyConfig); i { case 0: return &v.state @@ -5353,7 +5840,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[59].Exporter = func(v any, i int) any { switch v := v.(*SSHTunnelConfig); i { case 0: return &v.state @@ -5365,7 +5852,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { return nil } } - file_api_helm_app_gRPC_applist_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + file_api_helm_app_gRPC_applist_proto_msgTypes[60].Exporter = func(v any, i int) any { switch v := v.(*OCIRegistryResponse); i { case 0: return &v.state @@ -5384,7 +5871,7 @@ func file_api_helm_app_gRPC_applist_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_helm_app_gRPC_applist_proto_rawDesc, NumEnums: 1, - NumMessages: 58, + NumMessages: 63, NumExtensions: 0, NumServices: 1, }, diff --git a/api/helm-app/gRPC/applist.proto b/api/helm-app/gRPC/applist.proto index 4450b2b50b..4d36fd07e5 100644 --- a/api/helm-app/gRPC/applist.proto +++ b/api/helm-app/gRPC/applist.proto @@ -21,6 +21,7 @@ message AppListRequest { service ApplicationService { rpc ListApplications(AppListRequest) returns (stream DeployedAppList){} + rpc ListFluxApplications(AppListRequest) returns (stream FluxApplicationList){} rpc GetAppDetail(AppDetailRequest) returns (AppDetail){} rpc GetAppStatus(AppDetailRequest) returns (AppStatus){} rpc Hibernate(HibernateRequest) returns (HibernateResponse){} @@ -42,6 +43,8 @@ service ApplicationService { rpc UpgradeReleaseWithCustomChart(UpgradeReleaseRequest) returns(UpgradeReleaseResponse){} rpc ValidateOCIRegistry(RegistryCredential) returns(OCIRegistryResponse) {} rpc GetResourceTreeForExternalResources(ExternalResourceTreeRequest) returns(ResourceTreeResponse){} + rpc GetFluxAppDetail(FluxAppDetailRequest)returns(FluxAppDetail){} + } message ExternalResourceTreeRequest{ @@ -56,8 +59,39 @@ message ExternalResourceDetail { string name = 4; string namespace = 5; } +message FluxApplicationList { + int32 clusterId = 1; + repeated FluxApplication FluxApplication =2; + string errorMsg = 3; + bool errored = 4; +} +message FluxApplication{ + string name=1; + string healthStatus=2; + string syncStatus=3; + EnvironmentDetails environmentDetail = 4; + string fluxAppDeploymentType=5; +} +//---------------flux external app detail------- +message FluxAppDetailRequest{ + ClusterConfig clusterConfig = 1; + string namespace = 2; + string name = 3; + bool IsKustomizeApp =4; +} +message FluxAppDetail{ + FluxApplication fluxApplication=1; + FluxAppStatusDetail FluxAppStatusDetail = 2; + ResourceTreeResponse resourceTreeResponse =3; +} +message FluxAppStatusDetail{ + string Status = 1; + string Reason = 2; + string Message = 3; +} +//---------------flux external app detail ends here------- message DeployedAppList { repeated DeployedAppDetail DeployedAppDetail = 1; int32 clusterId = 2; diff --git a/api/helm-app/gRPC/applist_grpc.pb.go b/api/helm-app/gRPC/applist_grpc.pb.go index 296d5ee15d..3c8416b9ae 100644 --- a/api/helm-app/gRPC/applist_grpc.pb.go +++ b/api/helm-app/gRPC/applist_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.2.0 // - protoc v3.9.1 // source: api/helm-app/gRPC/applist.proto @@ -18,36 +18,12 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - ApplicationService_ListApplications_FullMethodName = "/ApplicationService/ListApplications" - ApplicationService_GetAppDetail_FullMethodName = "/ApplicationService/GetAppDetail" - ApplicationService_GetAppStatus_FullMethodName = "/ApplicationService/GetAppStatus" - ApplicationService_Hibernate_FullMethodName = "/ApplicationService/Hibernate" - ApplicationService_UnHibernate_FullMethodName = "/ApplicationService/UnHibernate" - ApplicationService_GetDeploymentHistory_FullMethodName = "/ApplicationService/GetDeploymentHistory" - ApplicationService_GetValuesYaml_FullMethodName = "/ApplicationService/GetValuesYaml" - ApplicationService_GetDesiredManifest_FullMethodName = "/ApplicationService/GetDesiredManifest" - ApplicationService_UninstallRelease_FullMethodName = "/ApplicationService/UninstallRelease" - ApplicationService_UpgradeRelease_FullMethodName = "/ApplicationService/UpgradeRelease" - ApplicationService_GetDeploymentDetail_FullMethodName = "/ApplicationService/GetDeploymentDetail" - ApplicationService_InstallRelease_FullMethodName = "/ApplicationService/InstallRelease" - ApplicationService_UpgradeReleaseWithChartInfo_FullMethodName = "/ApplicationService/UpgradeReleaseWithChartInfo" - ApplicationService_IsReleaseInstalled_FullMethodName = "/ApplicationService/IsReleaseInstalled" - ApplicationService_RollbackRelease_FullMethodName = "/ApplicationService/RollbackRelease" - ApplicationService_TemplateChart_FullMethodName = "/ApplicationService/TemplateChart" - ApplicationService_TemplateChartBulk_FullMethodName = "/ApplicationService/TemplateChartBulk" - ApplicationService_InstallReleaseWithCustomChart_FullMethodName = "/ApplicationService/InstallReleaseWithCustomChart" - ApplicationService_GetNotes_FullMethodName = "/ApplicationService/GetNotes" - ApplicationService_UpgradeReleaseWithCustomChart_FullMethodName = "/ApplicationService/UpgradeReleaseWithCustomChart" - ApplicationService_ValidateOCIRegistry_FullMethodName = "/ApplicationService/ValidateOCIRegistry" - ApplicationService_GetResourceTreeForExternalResources_FullMethodName = "/ApplicationService/GetResourceTreeForExternalResources" -) - // ApplicationServiceClient is the client API for ApplicationService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ApplicationServiceClient interface { ListApplications(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (ApplicationService_ListApplicationsClient, error) + ListFluxApplications(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (ApplicationService_ListFluxApplicationsClient, error) GetAppDetail(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*AppDetail, error) GetAppStatus(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*AppStatus, error) Hibernate(ctx context.Context, in *HibernateRequest, opts ...grpc.CallOption) (*HibernateResponse, error) @@ -69,6 +45,7 @@ type ApplicationServiceClient interface { UpgradeReleaseWithCustomChart(ctx context.Context, in *UpgradeReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) ValidateOCIRegistry(ctx context.Context, in *RegistryCredential, opts ...grpc.CallOption) (*OCIRegistryResponse, error) GetResourceTreeForExternalResources(ctx context.Context, in *ExternalResourceTreeRequest, opts ...grpc.CallOption) (*ResourceTreeResponse, error) + GetFluxAppDetail(ctx context.Context, in *FluxAppDetailRequest, opts ...grpc.CallOption) (*FluxAppDetail, error) } type applicationServiceClient struct { @@ -80,7 +57,7 @@ func NewApplicationServiceClient(cc grpc.ClientConnInterface) ApplicationService } func (c *applicationServiceClient) ListApplications(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (ApplicationService_ListApplicationsClient, error) { - stream, err := c.cc.NewStream(ctx, &ApplicationService_ServiceDesc.Streams[0], ApplicationService_ListApplications_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &ApplicationService_ServiceDesc.Streams[0], "/ApplicationService/ListApplications", opts...) if err != nil { return nil, err } @@ -111,9 +88,41 @@ func (x *applicationServiceListApplicationsClient) Recv() (*DeployedAppList, err return m, nil } +func (c *applicationServiceClient) ListFluxApplications(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (ApplicationService_ListFluxApplicationsClient, error) { + stream, err := c.cc.NewStream(ctx, &ApplicationService_ServiceDesc.Streams[1], "/ApplicationService/ListFluxApplications", opts...) + if err != nil { + return nil, err + } + x := &applicationServiceListFluxApplicationsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ApplicationService_ListFluxApplicationsClient interface { + Recv() (*FluxApplicationList, error) + grpc.ClientStream +} + +type applicationServiceListFluxApplicationsClient struct { + grpc.ClientStream +} + +func (x *applicationServiceListFluxApplicationsClient) Recv() (*FluxApplicationList, error) { + m := new(FluxApplicationList) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *applicationServiceClient) GetAppDetail(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*AppDetail, error) { out := new(AppDetail) - err := c.cc.Invoke(ctx, ApplicationService_GetAppDetail_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetAppDetail", in, out, opts...) if err != nil { return nil, err } @@ -122,7 +131,7 @@ func (c *applicationServiceClient) GetAppDetail(ctx context.Context, in *AppDeta func (c *applicationServiceClient) GetAppStatus(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*AppStatus, error) { out := new(AppStatus) - err := c.cc.Invoke(ctx, ApplicationService_GetAppStatus_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetAppStatus", in, out, opts...) if err != nil { return nil, err } @@ -131,7 +140,7 @@ func (c *applicationServiceClient) GetAppStatus(ctx context.Context, in *AppDeta func (c *applicationServiceClient) Hibernate(ctx context.Context, in *HibernateRequest, opts ...grpc.CallOption) (*HibernateResponse, error) { out := new(HibernateResponse) - err := c.cc.Invoke(ctx, ApplicationService_Hibernate_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/Hibernate", in, out, opts...) if err != nil { return nil, err } @@ -140,7 +149,7 @@ func (c *applicationServiceClient) Hibernate(ctx context.Context, in *HibernateR func (c *applicationServiceClient) UnHibernate(ctx context.Context, in *HibernateRequest, opts ...grpc.CallOption) (*HibernateResponse, error) { out := new(HibernateResponse) - err := c.cc.Invoke(ctx, ApplicationService_UnHibernate_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/UnHibernate", in, out, opts...) if err != nil { return nil, err } @@ -149,7 +158,7 @@ func (c *applicationServiceClient) UnHibernate(ctx context.Context, in *Hibernat func (c *applicationServiceClient) GetDeploymentHistory(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*HelmAppDeploymentHistory, error) { out := new(HelmAppDeploymentHistory) - err := c.cc.Invoke(ctx, ApplicationService_GetDeploymentHistory_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetDeploymentHistory", in, out, opts...) if err != nil { return nil, err } @@ -158,7 +167,7 @@ func (c *applicationServiceClient) GetDeploymentHistory(ctx context.Context, in func (c *applicationServiceClient) GetValuesYaml(ctx context.Context, in *AppDetailRequest, opts ...grpc.CallOption) (*ReleaseInfo, error) { out := new(ReleaseInfo) - err := c.cc.Invoke(ctx, ApplicationService_GetValuesYaml_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetValuesYaml", in, out, opts...) if err != nil { return nil, err } @@ -167,7 +176,7 @@ func (c *applicationServiceClient) GetValuesYaml(ctx context.Context, in *AppDet func (c *applicationServiceClient) GetDesiredManifest(ctx context.Context, in *ObjectRequest, opts ...grpc.CallOption) (*DesiredManifestResponse, error) { out := new(DesiredManifestResponse) - err := c.cc.Invoke(ctx, ApplicationService_GetDesiredManifest_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetDesiredManifest", in, out, opts...) if err != nil { return nil, err } @@ -176,7 +185,7 @@ func (c *applicationServiceClient) GetDesiredManifest(ctx context.Context, in *O func (c *applicationServiceClient) UninstallRelease(ctx context.Context, in *ReleaseIdentifier, opts ...grpc.CallOption) (*UninstallReleaseResponse, error) { out := new(UninstallReleaseResponse) - err := c.cc.Invoke(ctx, ApplicationService_UninstallRelease_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/UninstallRelease", in, out, opts...) if err != nil { return nil, err } @@ -185,7 +194,7 @@ func (c *applicationServiceClient) UninstallRelease(ctx context.Context, in *Rel func (c *applicationServiceClient) UpgradeRelease(ctx context.Context, in *UpgradeReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) { out := new(UpgradeReleaseResponse) - err := c.cc.Invoke(ctx, ApplicationService_UpgradeRelease_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/UpgradeRelease", in, out, opts...) if err != nil { return nil, err } @@ -194,7 +203,7 @@ func (c *applicationServiceClient) UpgradeRelease(ctx context.Context, in *Upgra func (c *applicationServiceClient) GetDeploymentDetail(ctx context.Context, in *DeploymentDetailRequest, opts ...grpc.CallOption) (*DeploymentDetailResponse, error) { out := new(DeploymentDetailResponse) - err := c.cc.Invoke(ctx, ApplicationService_GetDeploymentDetail_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetDeploymentDetail", in, out, opts...) if err != nil { return nil, err } @@ -203,7 +212,7 @@ func (c *applicationServiceClient) GetDeploymentDetail(ctx context.Context, in * func (c *applicationServiceClient) InstallRelease(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*InstallReleaseResponse, error) { out := new(InstallReleaseResponse) - err := c.cc.Invoke(ctx, ApplicationService_InstallRelease_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/InstallRelease", in, out, opts...) if err != nil { return nil, err } @@ -212,7 +221,7 @@ func (c *applicationServiceClient) InstallRelease(ctx context.Context, in *Insta func (c *applicationServiceClient) UpgradeReleaseWithChartInfo(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) { out := new(UpgradeReleaseResponse) - err := c.cc.Invoke(ctx, ApplicationService_UpgradeReleaseWithChartInfo_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/UpgradeReleaseWithChartInfo", in, out, opts...) if err != nil { return nil, err } @@ -221,7 +230,7 @@ func (c *applicationServiceClient) UpgradeReleaseWithChartInfo(ctx context.Conte func (c *applicationServiceClient) IsReleaseInstalled(ctx context.Context, in *ReleaseIdentifier, opts ...grpc.CallOption) (*BooleanResponse, error) { out := new(BooleanResponse) - err := c.cc.Invoke(ctx, ApplicationService_IsReleaseInstalled_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/IsReleaseInstalled", in, out, opts...) if err != nil { return nil, err } @@ -230,7 +239,7 @@ func (c *applicationServiceClient) IsReleaseInstalled(ctx context.Context, in *R func (c *applicationServiceClient) RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*BooleanResponse, error) { out := new(BooleanResponse) - err := c.cc.Invoke(ctx, ApplicationService_RollbackRelease_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/RollbackRelease", in, out, opts...) if err != nil { return nil, err } @@ -239,7 +248,7 @@ func (c *applicationServiceClient) RollbackRelease(ctx context.Context, in *Roll func (c *applicationServiceClient) TemplateChart(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*TemplateChartResponse, error) { out := new(TemplateChartResponse) - err := c.cc.Invoke(ctx, ApplicationService_TemplateChart_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/TemplateChart", in, out, opts...) if err != nil { return nil, err } @@ -248,7 +257,7 @@ func (c *applicationServiceClient) TemplateChart(ctx context.Context, in *Instal func (c *applicationServiceClient) TemplateChartBulk(ctx context.Context, in *BulkInstallReleaseRequest, opts ...grpc.CallOption) (*BulkTemplateChartResponse, error) { out := new(BulkTemplateChartResponse) - err := c.cc.Invoke(ctx, ApplicationService_TemplateChartBulk_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/TemplateChartBulk", in, out, opts...) if err != nil { return nil, err } @@ -257,7 +266,7 @@ func (c *applicationServiceClient) TemplateChartBulk(ctx context.Context, in *Bu func (c *applicationServiceClient) InstallReleaseWithCustomChart(ctx context.Context, in *HelmInstallCustomRequest, opts ...grpc.CallOption) (*HelmInstallCustomResponse, error) { out := new(HelmInstallCustomResponse) - err := c.cc.Invoke(ctx, ApplicationService_InstallReleaseWithCustomChart_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/InstallReleaseWithCustomChart", in, out, opts...) if err != nil { return nil, err } @@ -266,7 +275,7 @@ func (c *applicationServiceClient) InstallReleaseWithCustomChart(ctx context.Con func (c *applicationServiceClient) GetNotes(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*ChartNotesResponse, error) { out := new(ChartNotesResponse) - err := c.cc.Invoke(ctx, ApplicationService_GetNotes_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetNotes", in, out, opts...) if err != nil { return nil, err } @@ -275,7 +284,7 @@ func (c *applicationServiceClient) GetNotes(ctx context.Context, in *InstallRele func (c *applicationServiceClient) UpgradeReleaseWithCustomChart(ctx context.Context, in *UpgradeReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) { out := new(UpgradeReleaseResponse) - err := c.cc.Invoke(ctx, ApplicationService_UpgradeReleaseWithCustomChart_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/UpgradeReleaseWithCustomChart", in, out, opts...) if err != nil { return nil, err } @@ -284,7 +293,7 @@ func (c *applicationServiceClient) UpgradeReleaseWithCustomChart(ctx context.Con func (c *applicationServiceClient) ValidateOCIRegistry(ctx context.Context, in *RegistryCredential, opts ...grpc.CallOption) (*OCIRegistryResponse, error) { out := new(OCIRegistryResponse) - err := c.cc.Invoke(ctx, ApplicationService_ValidateOCIRegistry_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/ValidateOCIRegistry", in, out, opts...) if err != nil { return nil, err } @@ -293,7 +302,16 @@ func (c *applicationServiceClient) ValidateOCIRegistry(ctx context.Context, in * func (c *applicationServiceClient) GetResourceTreeForExternalResources(ctx context.Context, in *ExternalResourceTreeRequest, opts ...grpc.CallOption) (*ResourceTreeResponse, error) { out := new(ResourceTreeResponse) - err := c.cc.Invoke(ctx, ApplicationService_GetResourceTreeForExternalResources_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ApplicationService/GetResourceTreeForExternalResources", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *applicationServiceClient) GetFluxAppDetail(ctx context.Context, in *FluxAppDetailRequest, opts ...grpc.CallOption) (*FluxAppDetail, error) { + out := new(FluxAppDetail) + err := c.cc.Invoke(ctx, "/ApplicationService/GetFluxAppDetail", in, out, opts...) if err != nil { return nil, err } @@ -305,6 +323,7 @@ func (c *applicationServiceClient) GetResourceTreeForExternalResources(ctx conte // for forward compatibility type ApplicationServiceServer interface { ListApplications(*AppListRequest, ApplicationService_ListApplicationsServer) error + ListFluxApplications(*AppListRequest, ApplicationService_ListFluxApplicationsServer) error GetAppDetail(context.Context, *AppDetailRequest) (*AppDetail, error) GetAppStatus(context.Context, *AppDetailRequest) (*AppStatus, error) Hibernate(context.Context, *HibernateRequest) (*HibernateResponse, error) @@ -326,6 +345,7 @@ type ApplicationServiceServer interface { UpgradeReleaseWithCustomChart(context.Context, *UpgradeReleaseRequest) (*UpgradeReleaseResponse, error) ValidateOCIRegistry(context.Context, *RegistryCredential) (*OCIRegistryResponse, error) GetResourceTreeForExternalResources(context.Context, *ExternalResourceTreeRequest) (*ResourceTreeResponse, error) + GetFluxAppDetail(context.Context, *FluxAppDetailRequest) (*FluxAppDetail, error) mustEmbedUnimplementedApplicationServiceServer() } @@ -336,6 +356,9 @@ type UnimplementedApplicationServiceServer struct { func (UnimplementedApplicationServiceServer) ListApplications(*AppListRequest, ApplicationService_ListApplicationsServer) error { return status.Errorf(codes.Unimplemented, "method ListApplications not implemented") } +func (UnimplementedApplicationServiceServer) ListFluxApplications(*AppListRequest, ApplicationService_ListFluxApplicationsServer) error { + return status.Errorf(codes.Unimplemented, "method ListFluxApplications not implemented") +} func (UnimplementedApplicationServiceServer) GetAppDetail(context.Context, *AppDetailRequest) (*AppDetail, error) { return nil, status.Errorf(codes.Unimplemented, "method GetAppDetail not implemented") } @@ -399,6 +422,9 @@ func (UnimplementedApplicationServiceServer) ValidateOCIRegistry(context.Context func (UnimplementedApplicationServiceServer) GetResourceTreeForExternalResources(context.Context, *ExternalResourceTreeRequest) (*ResourceTreeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetResourceTreeForExternalResources not implemented") } +func (UnimplementedApplicationServiceServer) GetFluxAppDetail(context.Context, *FluxAppDetailRequest) (*FluxAppDetail, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFluxAppDetail not implemented") +} func (UnimplementedApplicationServiceServer) mustEmbedUnimplementedApplicationServiceServer() {} // UnsafeApplicationServiceServer may be embedded to opt out of forward compatibility for this service. @@ -433,6 +459,27 @@ func (x *applicationServiceListApplicationsServer) Send(m *DeployedAppList) erro return x.ServerStream.SendMsg(m) } +func _ApplicationService_ListFluxApplications_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(AppListRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ApplicationServiceServer).ListFluxApplications(m, &applicationServiceListFluxApplicationsServer{stream}) +} + +type ApplicationService_ListFluxApplicationsServer interface { + Send(*FluxApplicationList) error + grpc.ServerStream +} + +type applicationServiceListFluxApplicationsServer struct { + grpc.ServerStream +} + +func (x *applicationServiceListFluxApplicationsServer) Send(m *FluxApplicationList) error { + return x.ServerStream.SendMsg(m) +} + func _ApplicationService_GetAppDetail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AppDetailRequest) if err := dec(in); err != nil { @@ -443,7 +490,7 @@ func _ApplicationService_GetAppDetail_Handler(srv interface{}, ctx context.Conte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetAppDetail_FullMethodName, + FullMethod: "/ApplicationService/GetAppDetail", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetAppDetail(ctx, req.(*AppDetailRequest)) @@ -461,7 +508,7 @@ func _ApplicationService_GetAppStatus_Handler(srv interface{}, ctx context.Conte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetAppStatus_FullMethodName, + FullMethod: "/ApplicationService/GetAppStatus", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetAppStatus(ctx, req.(*AppDetailRequest)) @@ -479,7 +526,7 @@ func _ApplicationService_Hibernate_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_Hibernate_FullMethodName, + FullMethod: "/ApplicationService/Hibernate", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).Hibernate(ctx, req.(*HibernateRequest)) @@ -497,7 +544,7 @@ func _ApplicationService_UnHibernate_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_UnHibernate_FullMethodName, + FullMethod: "/ApplicationService/UnHibernate", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).UnHibernate(ctx, req.(*HibernateRequest)) @@ -515,7 +562,7 @@ func _ApplicationService_GetDeploymentHistory_Handler(srv interface{}, ctx conte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetDeploymentHistory_FullMethodName, + FullMethod: "/ApplicationService/GetDeploymentHistory", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetDeploymentHistory(ctx, req.(*AppDetailRequest)) @@ -533,7 +580,7 @@ func _ApplicationService_GetValuesYaml_Handler(srv interface{}, ctx context.Cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetValuesYaml_FullMethodName, + FullMethod: "/ApplicationService/GetValuesYaml", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetValuesYaml(ctx, req.(*AppDetailRequest)) @@ -551,7 +598,7 @@ func _ApplicationService_GetDesiredManifest_Handler(srv interface{}, ctx context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetDesiredManifest_FullMethodName, + FullMethod: "/ApplicationService/GetDesiredManifest", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetDesiredManifest(ctx, req.(*ObjectRequest)) @@ -569,7 +616,7 @@ func _ApplicationService_UninstallRelease_Handler(srv interface{}, ctx context.C } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_UninstallRelease_FullMethodName, + FullMethod: "/ApplicationService/UninstallRelease", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).UninstallRelease(ctx, req.(*ReleaseIdentifier)) @@ -587,7 +634,7 @@ func _ApplicationService_UpgradeRelease_Handler(srv interface{}, ctx context.Con } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_UpgradeRelease_FullMethodName, + FullMethod: "/ApplicationService/UpgradeRelease", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).UpgradeRelease(ctx, req.(*UpgradeReleaseRequest)) @@ -605,7 +652,7 @@ func _ApplicationService_GetDeploymentDetail_Handler(srv interface{}, ctx contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetDeploymentDetail_FullMethodName, + FullMethod: "/ApplicationService/GetDeploymentDetail", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetDeploymentDetail(ctx, req.(*DeploymentDetailRequest)) @@ -623,7 +670,7 @@ func _ApplicationService_InstallRelease_Handler(srv interface{}, ctx context.Con } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_InstallRelease_FullMethodName, + FullMethod: "/ApplicationService/InstallRelease", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).InstallRelease(ctx, req.(*InstallReleaseRequest)) @@ -641,7 +688,7 @@ func _ApplicationService_UpgradeReleaseWithChartInfo_Handler(srv interface{}, ct } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_UpgradeReleaseWithChartInfo_FullMethodName, + FullMethod: "/ApplicationService/UpgradeReleaseWithChartInfo", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).UpgradeReleaseWithChartInfo(ctx, req.(*InstallReleaseRequest)) @@ -659,7 +706,7 @@ func _ApplicationService_IsReleaseInstalled_Handler(srv interface{}, ctx context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_IsReleaseInstalled_FullMethodName, + FullMethod: "/ApplicationService/IsReleaseInstalled", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).IsReleaseInstalled(ctx, req.(*ReleaseIdentifier)) @@ -677,7 +724,7 @@ func _ApplicationService_RollbackRelease_Handler(srv interface{}, ctx context.Co } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_RollbackRelease_FullMethodName, + FullMethod: "/ApplicationService/RollbackRelease", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).RollbackRelease(ctx, req.(*RollbackReleaseRequest)) @@ -695,7 +742,7 @@ func _ApplicationService_TemplateChart_Handler(srv interface{}, ctx context.Cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_TemplateChart_FullMethodName, + FullMethod: "/ApplicationService/TemplateChart", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).TemplateChart(ctx, req.(*InstallReleaseRequest)) @@ -713,7 +760,7 @@ func _ApplicationService_TemplateChartBulk_Handler(srv interface{}, ctx context. } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_TemplateChartBulk_FullMethodName, + FullMethod: "/ApplicationService/TemplateChartBulk", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).TemplateChartBulk(ctx, req.(*BulkInstallReleaseRequest)) @@ -731,7 +778,7 @@ func _ApplicationService_InstallReleaseWithCustomChart_Handler(srv interface{}, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_InstallReleaseWithCustomChart_FullMethodName, + FullMethod: "/ApplicationService/InstallReleaseWithCustomChart", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).InstallReleaseWithCustomChart(ctx, req.(*HelmInstallCustomRequest)) @@ -749,7 +796,7 @@ func _ApplicationService_GetNotes_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetNotes_FullMethodName, + FullMethod: "/ApplicationService/GetNotes", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetNotes(ctx, req.(*InstallReleaseRequest)) @@ -767,7 +814,7 @@ func _ApplicationService_UpgradeReleaseWithCustomChart_Handler(srv interface{}, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_UpgradeReleaseWithCustomChart_FullMethodName, + FullMethod: "/ApplicationService/UpgradeReleaseWithCustomChart", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).UpgradeReleaseWithCustomChart(ctx, req.(*UpgradeReleaseRequest)) @@ -785,7 +832,7 @@ func _ApplicationService_ValidateOCIRegistry_Handler(srv interface{}, ctx contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_ValidateOCIRegistry_FullMethodName, + FullMethod: "/ApplicationService/ValidateOCIRegistry", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).ValidateOCIRegistry(ctx, req.(*RegistryCredential)) @@ -803,7 +850,7 @@ func _ApplicationService_GetResourceTreeForExternalResources_Handler(srv interfa } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ApplicationService_GetResourceTreeForExternalResources_FullMethodName, + FullMethod: "/ApplicationService/GetResourceTreeForExternalResources", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ApplicationServiceServer).GetResourceTreeForExternalResources(ctx, req.(*ExternalResourceTreeRequest)) @@ -811,6 +858,24 @@ func _ApplicationService_GetResourceTreeForExternalResources_Handler(srv interfa return interceptor(ctx, in, info, handler) } +func _ApplicationService_GetFluxAppDetail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FluxAppDetailRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApplicationServiceServer).GetFluxAppDetail(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ApplicationService/GetFluxAppDetail", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApplicationServiceServer).GetFluxAppDetail(ctx, req.(*FluxAppDetailRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ApplicationService_ServiceDesc is the grpc.ServiceDesc for ApplicationService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -902,6 +967,10 @@ var ApplicationService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetResourceTreeForExternalResources", Handler: _ApplicationService_GetResourceTreeForExternalResources_Handler, }, + { + MethodName: "GetFluxAppDetail", + Handler: _ApplicationService_GetFluxAppDetail_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -909,6 +978,11 @@ var ApplicationService_ServiceDesc = grpc.ServiceDesc{ Handler: _ApplicationService_ListApplications_Handler, ServerStreams: true, }, + { + StreamName: "ListFluxApplications", + Handler: _ApplicationService_ListFluxApplications_Handler, + ServerStreams: true, + }, }, Metadata: "api/helm-app/gRPC/applist.proto", } diff --git a/api/helm-app/service/HelmAppService.go b/api/helm-app/service/HelmAppService.go index de353fe30b..b9a7afdf66 100644 --- a/api/helm-app/service/HelmAppService.go +++ b/api/helm-app/service/HelmAppService.go @@ -192,15 +192,18 @@ func (impl *HelmAppServiceImpl) ListHelmApplications(ctx context.Context, cluste func (impl *HelmAppServiceImpl) HibernateApplication(ctx context.Context, app *helmBean.AppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { conf, err := impl.GetClusterConf(app.ClusterId) if err != nil { + + impl.logger.Errorw("HibernateApplication", "error in getting cluster config", "err", err, "clusterId", app.ClusterId) return nil, err } - req := impl.hibernateReqAdaptor(hibernateRequest) + req := HibernateReqAdaptor(hibernateRequest) req.ClusterConfig = conf res, err := impl.helmAppClient.Hibernate(ctx, req) if err != nil { + impl.logger.Errorw("HibernateApplication", "error in hibernating the resources", "err", err, "clusterId", app.ClusterId, "appReleaseName", app.ReleaseName) return nil, err } - response := impl.hibernateResponseAdaptor(res.Status) + response := HibernateResponseAdaptor(res.Status) return response, nil } @@ -208,15 +211,18 @@ func (impl *HelmAppServiceImpl) UnHibernateApplication(ctx context.Context, app conf, err := impl.GetClusterConf(app.ClusterId) if err != nil { + impl.logger.Errorw("UnHibernateApplication", "error in getting cluster config", "err", err, "clusterId", app.ClusterId) return nil, err } - req := impl.hibernateReqAdaptor(hibernateRequest) + req := HibernateReqAdaptor(hibernateRequest) req.ClusterConfig = conf res, err := impl.helmAppClient.UnHibernate(ctx, req) if err != nil { + impl.logger.Errorw("UnHibernateApplication", "error in UnHibernating the resources", "err", err, "clusterId", app.ClusterId, "appReleaseName", app.ReleaseName) + return nil, err } - response := impl.hibernateResponseAdaptor(res.Status) + response := HibernateResponseAdaptor(res.Status) return response, nil } @@ -1109,40 +1115,6 @@ func (impl *HelmAppServiceImpl) listApplications(ctx context.Context, clusterIds return applicatonStream, err } -func (impl *HelmAppServiceImpl) hibernateReqAdaptor(hibernateRequest *openapi.HibernateRequest) *gRPC.HibernateRequest { - req := &gRPC.HibernateRequest{} - for _, reqObject := range hibernateRequest.GetResources() { - obj := &gRPC.ObjectIdentifier{ - Group: *reqObject.Group, - Kind: *reqObject.Kind, - Version: *reqObject.Version, - Name: *reqObject.Name, - Namespace: *reqObject.Namespace, - } - req.ObjectIdentifier = append(req.ObjectIdentifier, obj) - } - return req -} - -func (impl *HelmAppServiceImpl) hibernateResponseAdaptor(in []*gRPC.HibernateStatus) []*openapi.HibernateStatus { - var resStatus []*openapi.HibernateStatus - for _, status := range in { - resObj := &openapi.HibernateStatus{ - Success: &status.Success, - ErrorMessage: &status.ErrorMsg, - TargetObject: &openapi.HibernateTargetObject{ - Group: &status.TargetObject.Group, - Kind: &status.TargetObject.Kind, - Version: &status.TargetObject.Version, - Name: &status.TargetObject.Name, - Namespace: &status.TargetObject.Namespace, - }, - } - resStatus = append(resStatus, resObj) - } - return resStatus -} - func isSameAppName(deployedAppName string, appDto app.App) bool { if len(appDto.DisplayName) > 0 { return deployedAppName == appDto.DisplayName diff --git a/api/helm-app/service/helper.go b/api/helm-app/service/helper.go index 45f69c70d9..50a6798cc7 100644 --- a/api/helm-app/service/helper.go +++ b/api/helm-app/service/helper.go @@ -18,7 +18,10 @@ package service import ( "fmt" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/api/helm-app/service/bean" + "net/http" "strconv" "strings" ) @@ -41,3 +44,44 @@ func DecodeExternalAppAppId(appId string) (*bean.AppIdentifier, error) { ReleaseName: component[2], }, nil } + +func HibernateReqAdaptor(hibernateRequest *openapi.HibernateRequest) *gRPC.HibernateRequest { + req := &gRPC.HibernateRequest{} + for _, reqObject := range hibernateRequest.GetResources() { + obj := &gRPC.ObjectIdentifier{ + Group: *reqObject.Group, + Kind: *reqObject.Kind, + Version: *reqObject.Version, + Name: *reqObject.Name, + Namespace: *reqObject.Namespace, + } + req.ObjectIdentifier = append(req.ObjectIdentifier, obj) + } + return req +} + +func HibernateResponseAdaptor(in []*gRPC.HibernateStatus) []*openapi.HibernateStatus { + var resStatus []*openapi.HibernateStatus + for _, status := range in { + resObj := &openapi.HibernateStatus{ + Success: &status.Success, + ErrorMessage: &status.ErrorMsg, + TargetObject: &openapi.HibernateTargetObject{ + Group: &status.TargetObject.Group, + Kind: &status.TargetObject.Kind, + Version: &status.TargetObject.Version, + Name: &status.TargetObject.Name, + Namespace: &status.TargetObject.Namespace, + }, + } + resStatus = append(resStatus, resObj) + } + return resStatus +} + +func GetStatusCode(err error) int { + if err.Error() == "unauthorized" { + return http.StatusForbidden + } + return http.StatusInternalServerError +} diff --git a/api/k8s/application/k8sApplicationRestHandler.go b/api/k8s/application/k8sApplicationRestHandler.go index 823fdba4c0..b6830b7d0d 100644 --- a/api/k8s/application/k8sApplicationRestHandler.go +++ b/api/k8s/application/k8sApplicationRestHandler.go @@ -29,13 +29,16 @@ import ( "github.com/devtron-labs/common-lib/utils/k8sObjectsUtil" "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/api/restHandler/common" util2 "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/argoApplication" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/cluster" clientErrors "github.com/devtron-labs/devtron/pkg/errors" + "github.com/devtron-labs/devtron/pkg/fluxApplication" "github.com/devtron-labs/devtron/pkg/k8s" application2 "github.com/devtron-labs/devtron/pkg/k8s/application" bean2 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" @@ -90,9 +93,12 @@ type K8sApplicationRestHandlerImpl struct { userService user.UserService k8sCommonService k8s.K8sCommonService terminalEnvVariables *util.TerminalEnvVariables + fluxAppService fluxApplication.FluxApplicationService + argoApplication argoApplication.ArgoApplicationService } -func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate, envVariables *util.EnvironmentVariables) *K8sApplicationRestHandlerImpl { +func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate, envVariables *util.EnvironmentVariables, fluxAppService fluxApplication.FluxApplicationService, argoApplication argoApplication.ArgoApplicationService, +) *K8sApplicationRestHandlerImpl { return &K8sApplicationRestHandlerImpl{ logger: logger, k8sApplicationService: k8sApplicationService, @@ -106,6 +112,8 @@ func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationS userService: userService, k8sCommonService: k8sCommonService, terminalEnvVariables: envVariables.TerminalEnvVariables, + fluxAppService: fluxAppService, + argoApplication: argoApplication, } } @@ -160,61 +168,19 @@ func (handler *K8sApplicationRestHandlerImpl) GetResource(w http.ResponseWriter, common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - vars := r.URL.Query() - request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") - rbacObject := "" - rbacObject2 := "" - envObject := "" + token := r.Header.Get("token") - if request.AppId != "" && request.AppType == bean2.HelmAppType { - appIdentifier, err := handler.helmAppService.DecodeAppId(request.AppId) + + //rbac validation for the apps requests + if request.AppId != "" { + ok, err := handler.verifyRbacForAppRequests(token, &request, r, casbin.ActionGet) if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return - } - //setting appIdentifier value in request - request.AppIdentifier = appIdentifier - request.ClusterId = request.AppIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Helm App - rbacObject, rbacObject2 = handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(request.AppIdentifier.ClusterId, request.AppIdentifier.Namespace, request.AppIdentifier.ReleaseName) - ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject2) - if !ok { + } else if !ok { common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) return } - // RBAC enforcer Ends - } else if request.AppId != "" && request.AppType == bean2.DevtronAppType { - devtronAppIdentifier, err := handler.k8sApplicationService.DecodeDevtronAppId(request.AppId) - if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - //setting devtronAppIdentifier value in request - request.DevtronAppIdentifier = devtronAppIdentifier - request.ClusterId = request.DevtronAppIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Devtron App - envObject = handler.enforcerUtil.GetEnvRBACNameByAppId(request.DevtronAppIdentifier.AppId, request.DevtronAppIdentifier.EnvId) - hasReadAccessForEnv := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionGet, envObject) - if !hasReadAccessForEnv { - common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) - return - } - // RBAC enforcer Ends } // Invalid cluster id if request.ClusterId <= 0 { @@ -266,69 +232,147 @@ func (handler *K8sApplicationRestHandlerImpl) GetResource(w http.ResponseWriter, common.WriteJsonResp(w, nil, resource, http.StatusOK) } - func (handler *K8sApplicationRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - clusterIdString := vars["appId"] - if clusterIdString == "" { + appIdString := vars["appId"] + if appIdString == "" { common.WriteJsonResp(w, fmt.Errorf("empty appid in request"), nil, http.StatusBadRequest) return } - appIdentifier, err := handler.helmAppService.DecodeAppId(clusterIdString) + appTypeString := vars["appType"] + if appTypeString == "" { + common.WriteJsonResp(w, fmt.Errorf("empty appType in request"), nil, http.StatusBadRequest) + return + } + appType, err := strconv.Atoi(appTypeString) if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + common.WriteJsonResp(w, fmt.Errorf("invalid appType in request"), nil, http.StatusBadRequest) return } - // RBAC enforcer applying - rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + token := r.Header.Get("token") + var k8sAppDetail bean.AppDetailContainer + var resourceTreeResponse *gRPC.ResourceTreeResponse + var clusterId int + var namespace string + var resourceTreeInf map[string]interface{} + var externalArgoApplicationName string - ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject2) + if appType == bean2.HelmAppType { + appIdentifier, err := handler.helmAppService.DecodeAppId(appIdString) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + // RBAC enforcer applying + rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) - if !ok { - common.WriteJsonResp(w, fmt.Errorf("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - appDetail, err := handler.helmAppService.GetApplicationDetail(r.Context(), appIdentifier) - if err != nil { - apiError := clientErrors.ConvertToApiError(err) - if apiError != nil { - err = apiError + ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject2) + + if !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized"), nil, http.StatusForbidden) + return } - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return + //RBAC enforcer Ends + appDetail, err := handler.helmAppService.GetApplicationDetail(r.Context(), appIdentifier) + if err != nil { + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + + clusterId = appIdentifier.ClusterId + namespace = appIdentifier.Namespace + resourceTreeResponse = appDetail.ResourceTreeResponse + + } else if appType == bean2.ArgoAppType { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(appIdString) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + // RBAC enforcer applying + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer Ends + + appDetail, err := handler.argoApplication.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) + if err != nil { + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + clusterId = appIdentifier.ClusterId + namespace = appIdentifier.Namespace + resourceTreeResponse = appDetail.ResourceTree + externalArgoApplicationName = appIdentifier.AppName + + } else if appType == bean2.FluxAppType { + appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(appIdString) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + // RBAC enforcer applying + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer Ends + + appDetail, err := handler.fluxAppService.GetFluxAppDetail(r.Context(), appIdentifier) + if err != nil { + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + clusterId = appIdentifier.ClusterId + namespace = appIdentifier.Namespace + resourceTreeResponse = appDetail.ResourceTreeResponse } - k8sAppDetail := bean.AppDetailContainer{ + + k8sAppDetail = bean.AppDetailContainer{ DeploymentDetailContainer: bean.DeploymentDetailContainer{ - ClusterId: appIdentifier.ClusterId, - Namespace: appIdentifier.Namespace, + ClusterId: clusterId, + Namespace: namespace, }, } - var resourceTreeInf map[string]interface{} - bytes, _ := json.Marshal(appDetail.ResourceTreeResponse) + + bytes, _ := json.Marshal(resourceTreeResponse) err = json.Unmarshal(bytes, &resourceTreeInf) if err != nil { common.WriteJsonResp(w, fmt.Errorf("unmarshal error of resource tree response"), nil, http.StatusInternalServerError) return } - validRequests := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTreeInf, k8sAppDetail, clusterIdString, []string{k8sCommonBean.ServiceKind, k8sCommonBean.IngressKind}) + + validRequests := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTreeInf, k8sAppDetail, appIdString, []string{k8sCommonBean.ServiceKind, k8sCommonBean.IngressKind}, externalArgoApplicationName) if len(validRequests) == 0 { - handler.logger.Error("neither service nor ingress found for this app", "appId", clusterIdString) + handler.logger.Error("neither service nor ingress found for this app", "appId", appIdString) common.WriteJsonResp(w, err, nil, http.StatusNoContent) return } resp, err := handler.k8sCommonService.GetManifestsByBatch(r.Context(), validRequests) if err != nil { - handler.logger.Errorw("error in getting manifests in batch", "err", err, "clusterId", appIdentifier.ClusterId) + handler.logger.Errorw("error in getting manifests in batch", "err", err, "clusterId", k8sAppDetail.ClusterId) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } result := handler.k8sApplicationService.GetUrlsByBatchForIngress(r.Context(), resp) common.WriteJsonResp(w, nil, result, http.StatusOK) -} +} func (handler *K8sApplicationRestHandlerImpl) CreateResource(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) var request k8s.ResourceRequestBean @@ -363,69 +407,27 @@ func (handler *K8sApplicationRestHandlerImpl) CreateResource(w http.ResponseWrit } common.WriteJsonResp(w, nil, resource, http.StatusOK) } - func (handler *K8sApplicationRestHandlerImpl) UpdateResource(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - token := r.Header.Get("token") var request k8s.ResourceRequestBean + token := r.Header.Get("token") err := decoder.Decode(&request) if err != nil { handler.logger.Errorw("error in decoding request body", "err", err) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - if request.AppId != "" && request.AppType == bean2.HelmAppType { - // For helm app resources - appIdentifier, err := handler.helmAppService.DecodeAppId(request.AppId) - if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - //setting appIdentifier value in request - request.AppIdentifier = appIdentifier - request.ClusterId = appIdentifier.ClusterId - if request.DeploymentType == bean2.HelmAppType { - if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying - rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(request.AppIdentifier.ClusterId, request.AppIdentifier.Namespace, request.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, errors2.New("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - } else if request.AppId != "" && request.AppType == bean2.DevtronAppType { - // For Devtron App resources - devtronAppIdentifier, err := handler.k8sApplicationService.DecodeDevtronAppId(request.AppId) + + //rbac validation for the apps requests + if request.AppId != "" { + ok, err := handler.verifyRbacForAppRequests(token, &request, r, casbin.ActionUpdate) if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return - } - //setting devtronAppIdentifier value in request - request.DevtronAppIdentifier = devtronAppIdentifier - request.ClusterId = request.DevtronAppIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Devtron App - envObject := handler.enforcerUtil.GetEnvRBACNameByAppId(request.DevtronAppIdentifier.AppId, request.DevtronAppIdentifier.EnvId) - hasAccessForEnv := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionUpdate, envObject) - if !hasAccessForEnv { + } else if !ok { common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) return } - // RBAC enforcer Ends } else if request.ClusterId > 0 { // RBAC enforcer applying for Resource Browser if ok := handler.handleRbac(r, w, request, token, casbin.ActionUpdate); !ok { @@ -445,7 +447,6 @@ func (handler *K8sApplicationRestHandlerImpl) UpdateResource(w http.ResponseWrit } common.WriteJsonResp(w, nil, resource, http.StatusOK) } - func (handler *K8sApplicationRestHandlerImpl) handleRbac(r *http.Request, w http.ResponseWriter, request k8s.ResourceRequestBean, token string, casbinAction string) bool { // assume direct update in cluster allowed, err := handler.k8sApplicationService.ValidateClusterResourceRequest(r.Context(), &request, handler.getRbacCallbackForResource(token, casbinAction)) @@ -458,7 +459,6 @@ func (handler *K8sApplicationRestHandlerImpl) handleRbac(r *http.Request, w http } return allowed } - func (handler *K8sApplicationRestHandlerImpl) DeleteResource(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { @@ -473,60 +473,19 @@ func (handler *K8sApplicationRestHandlerImpl) DeleteResource(w http.ResponseWrit return } token := r.Header.Get("token") + vars := r.URL.Query() + request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") - if request.AppId != "" && request.AppType == bean2.HelmAppType { - // For Helm app resource - appIdentifier, err := handler.helmAppService.DecodeAppId(request.AppId) - if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - //setting appIdentifier value in request - request.AppIdentifier = appIdentifier - request.ClusterId = appIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Helm App - rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(request.AppIdentifier.ClusterId, request.AppIdentifier.Namespace, request.AppIdentifier.ReleaseName) - - ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionDelete, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionDelete, rbacObject2) - - if !ok { - common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - } else if request.AppId != "" && request.AppType == bean2.DevtronAppType { - // For Devtron App resources - devtronAppIdentifier, err := handler.k8sApplicationService.DecodeDevtronAppId(request.AppId) + //rbac handle for the apps requests + if request.AppId != "" { + ok, err := handler.verifyRbacForAppRequests(token, &request, r, casbin.ActionDelete) if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return - } - //setting devtronAppIdentifier value in request - request.DevtronAppIdentifier = devtronAppIdentifier - request.ClusterId = request.DevtronAppIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Devtron App - envObject := handler.enforcerUtil.GetEnvRBACNameByAppId(request.DevtronAppIdentifier.AppId, request.DevtronAppIdentifier.EnvId) - hasAccessForEnv := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionDelete, envObject) - if !hasAccessForEnv { + } else if !ok { common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) return } - // RBAC enforcer Ends } else if request.ClusterId > 0 { // RBAC enforcer applying for resource Browser if ok := handler.handleRbac(r, w, request, token, casbin.ActionDelete); !ok { @@ -555,7 +514,6 @@ func (handler *K8sApplicationRestHandlerImpl) DeleteResource(w http.ResponseWrit } common.WriteJsonResp(w, nil, resource, http.StatusOK) } - func (handler *K8sApplicationRestHandlerImpl) ListEvents(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) token := r.Header.Get("token") @@ -566,66 +524,23 @@ func (handler *K8sApplicationRestHandlerImpl) ListEvents(w http.ResponseWriter, common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - vars := r.URL.Query() - request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") - if request.AppId != "" && request.AppType == bean2.HelmAppType { - // For Helm app resource - appIdentifier, err := handler.helmAppService.DecodeAppId(request.AppId) + //rbac validation for the apps requests + if request.AppId != "" { + ok, err := handler.verifyRbacForAppRequests(token, &request, r, casbin.ActionGet) if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return - } - //setting appIdentifier value in request - request.AppIdentifier = appIdentifier - request.ClusterId = appIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - // RBAC enforcer applying for Helm App - rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(request.AppIdentifier.ClusterId, request.AppIdentifier.Namespace, request.AppIdentifier.ReleaseName) - ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject2) - if !ok { - common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - } else if request.AppId != "" && request.AppType == bean2.DevtronAppType { - // For Devtron App resources - devtronAppIdentifier, err := handler.k8sApplicationService.DecodeDevtronAppId(request.AppId) - if err != nil { - handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - //setting devtronAppIdentifier value in request - request.DevtronAppIdentifier = devtronAppIdentifier - request.ClusterId = request.DevtronAppIdentifier.ClusterId - if request.DeploymentType == bean2.HelmInstalledType { - //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs - } else if request.DeploymentType == bean2.ArgoInstalledType { - //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree - } - //RBAC enforcer applying for Devtron App - envObject := handler.enforcerUtil.GetEnvRBACNameByAppId(request.DevtronAppIdentifier.AppId, request.DevtronAppIdentifier.EnvId) - hasAccessForEnv := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionGet, envObject) - if !hasAccessForEnv { - common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) + } else if !ok { + common.WriteJsonResp(w, errors2.New("unauthorized user"), nil, http.StatusForbidden) return } - //RBAC enforcer Ends - } else if request.ClusterId > 0 && request.AppType != bean2.ArgoAppType { + } else if request.ClusterId > 0 { // RBAC enforcer applying for resource Browser if ok := handler.handleRbac(r, w, request, token, casbin.ActionGet); !ok { return } // RBAC enforcer Ends - } else if request.ClusterId <= 0 { + } else { common.WriteJsonResp(w, errors.New("can not get resource as target cluster is not provided"), nil, http.StatusBadRequest) return } @@ -637,7 +552,6 @@ func (handler *K8sApplicationRestHandlerImpl) ListEvents(w http.ResponseWriter, } common.WriteJsonResp(w, nil, events, http.StatusOK) } - func (handler *K8sApplicationRestHandlerImpl) GetPodLogs(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("token") request, err := handler.k8sApplicationService.ValidatePodLogsRequestQuery(r) @@ -761,7 +675,7 @@ func generatePodLogsFilename(filename string) string { } func (handler *K8sApplicationRestHandlerImpl) requestValidationAndRBAC(w http.ResponseWriter, r *http.Request, token string, request *k8s.ResourceRequestBean) { - if request.AppIdentifier != nil { + if request.AppType == bean2.HelmAppType && request.AppIdentifier != nil { if request.DeploymentType == bean2.HelmInstalledType { if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { common.WriteJsonResp(w, err, nil, http.StatusBadRequest) @@ -779,7 +693,7 @@ func (handler *K8sApplicationRestHandlerImpl) requestValidationAndRBAC(w http.Re return } //RBAC enforcer Ends - } else if request.DevtronAppIdentifier != nil { + } else if request.AppType == bean2.DevtronAppType && request.DevtronAppIdentifier != nil { if request.DeploymentType == bean2.HelmInstalledType { //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs } else if request.DeploymentType == bean2.ArgoInstalledType { @@ -792,7 +706,39 @@ func (handler *K8sApplicationRestHandlerImpl) requestValidationAndRBAC(w http.Re return } //RBAC enforcer Ends - } else if request.AppIdentifier == nil && request.DevtronAppIdentifier == nil && request.ClusterId > 0 && request.AppType != bean2.ArgoAppType { + } else if request.AppType == bean2.FluxAppType && request.ExternalFluxAppIdentifier != nil { + valid, err := handler.k8sApplicationService.ValidateFluxResourceRequest(r.Context(), request.ExternalFluxAppIdentifier, request.K8sRequest) + if err != nil || !valid { + handler.logger.Errorw("error in validating resource request", "err", err) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer ends here + } else if request.AppType == bean2.ArgoAppType && request.ExternalArgoApplicationName != "" { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.AppId) + if err != nil { + handler.logger.Errorw(bean2.AppIdDecodingError, "err", err, "appIdentifier", request.AppIdentifier) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + } + valid, err := handler.k8sApplicationService.ValidateArgoResourceRequest(r.Context(), appIdentifier, request.K8sRequest) + if err != nil || !valid { + handler.logger.Errorw("error in validating resource request", "err", err) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer ends here + } else if request.AppIdentifier == nil && request.DevtronAppIdentifier == nil && request.ClusterId > 0 && request.ExternalArgoApplicationName == "" { //RBAC enforcer applying For Resource Browser if !handler.handleRbac(r, w, *request, token, casbin.ActionGet) { return @@ -822,15 +768,11 @@ func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.Response common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) return } - vars := r.URL.Query() - appTypeStr := vars.Get("appType") - appType, _ := strconv.Atoi(appTypeStr) //ignore error as this var is not expected for devtron apps/helm apps/resource bowser. appType var is needed in case of Argo Apps request, resourceRequestBean, err := handler.k8sApplicationService.ValidateTerminalRequestQuery(r) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") // check for super admin restricted := handler.restrictTerminalAccessForNonSuperUsers(w, token) if restricted { @@ -854,7 +796,23 @@ func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.Response return } //RBAC enforcer Ends - } else if resourceRequestBean.AppIdentifier == nil && resourceRequestBean.DevtronAppIdentifier == nil && resourceRequestBean.ClusterId > 0 && appType != bean2.ArgoAppType { + } else if resourceRequestBean.ExternalFluxAppIdentifier != nil { + // RBAC enforcer applying For external flux app + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*"); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer Ends + + } else if resourceRequestBean.ExternalArgoApplicationName != "" { + // RBAC enforcer applying For external Argo app + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*"); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer Ends + + } else if resourceRequestBean.AppIdentifier == nil && resourceRequestBean.DevtronAppIdentifier == nil && resourceRequestBean.ExternalFluxAppIdentifier == nil && resourceRequestBean.ExternalArgoApplicationName == "" && resourceRequestBean.ClusterId > 0 { //RBAC enforcer applying for Resource Browser if !handler.handleRbac(r, w, *resourceRequestBean, token, casbin.ActionUpdate) { return @@ -1060,8 +1018,6 @@ func (handler *K8sApplicationRestHandlerImpl) CreateEphemeralContainer(w http.Re return } request.UserId = userId - vars := r.URL.Query() - request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") err = handler.k8sApplicationService.CreatePodEphemeralContainers(&request) if err != nil { handler.logger.Errorw("error occurred in creating ephemeral container", "err", err, "requestPayload", request) @@ -1110,8 +1066,6 @@ func (handler *K8sApplicationRestHandlerImpl) DeleteEphemeralContainer(w http.Re return } request.UserId = userId - vars := r.URL.Query() - request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") _, err = handler.k8sApplicationService.TerminatePodEphemeralContainer(request) if err != nil { handler.logger.Errorw("error occurred in terminating ephemeral container", "err", err, "requestPayload", request) @@ -1130,10 +1084,6 @@ func (handler *K8sApplicationRestHandlerImpl) handleEphemeralRBAC(podName, names common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return resourceRequestBean } - vars := r.URL.Query() - appTypeStr := vars.Get("appType") - resourceRequestBean.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") - appType, _ := strconv.Atoi(appTypeStr) //ignore error as this var is not expected for devtron apps/helm apps/resource bowser. appType var is needed in case of Argo Apps if resourceRequestBean.AppIdentifier != nil { // RBAC enforcer applying For Helm App rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(resourceRequestBean.AppIdentifier.ClusterId, resourceRequestBean.AppIdentifier.Namespace, resourceRequestBean.AppIdentifier.ReleaseName) @@ -1152,7 +1102,22 @@ func (handler *K8sApplicationRestHandlerImpl) handleEphemeralRBAC(podName, names return resourceRequestBean } //RBAC enforcer Ends - } else if resourceRequestBean.AppIdentifier == nil && resourceRequestBean.DevtronAppIdentifier == nil && resourceRequestBean.ClusterId > 0 && appType != bean2.ArgoAppType { + } else if resourceRequestBean.ExternalFluxAppIdentifier != nil { + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) + return resourceRequestBean + } + //RBAC enforcer ends here + } else if resourceRequestBean.ExternalArgoApplicationName != "" { + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok { + common.WriteJsonResp(w, errors2.New("unauthorized"), nil, http.StatusForbidden) + return resourceRequestBean + } + //RBAC enforcer ends here + + } else if resourceRequestBean.AppIdentifier == nil && resourceRequestBean.DevtronAppIdentifier == nil && resourceRequestBean.ExternalArgoApplicationName == "" && resourceRequestBean.ExternalFluxAppIdentifier == nil && resourceRequestBean.ClusterId > 0 { //RBAC enforcer applying for Resource Browser resourceRequestBean.K8sRequest.ResourceIdentifier.Name = podName resourceRequestBean.K8sRequest.ResourceIdentifier.Namespace = namespace @@ -1166,3 +1131,107 @@ func (handler *K8sApplicationRestHandlerImpl) handleEphemeralRBAC(podName, names } return resourceRequestBean } + +/* + true and err =!nil --> not possible [indicates that authorized but error has occurred too.] + true and err ==nil --> Denotes that user is authorized without any error, we can proceed + false and err !=nil --> during the validation of resources, we got an error, resulting the StatusBadRequest + false and err == nil --> denotes that user is not authorized, resulting in Unauthorized +*/ +func (handler *K8sApplicationRestHandlerImpl) verifyRbacForAppRequests(token string, request *k8s.ResourceRequestBean, r *http.Request, actionType string) (bool, error) { + rbacObject := "" + rbacObject2 := "" + envObject := "" + switch request.AppType { + case bean2.ArgoAppType: + argoAppIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.AppId) + if err != nil { + handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) + return false, err + } + request.ClusterId = argoAppIdentifier.ClusterId + request.ExternalArgoApplicationName = argoAppIdentifier.AppName + valid, err := handler.k8sApplicationService.ValidateArgoResourceRequest(r.Context(), argoAppIdentifier, request.K8sRequest) + if err != nil || !valid { + handler.logger.Errorw("error in validating resource request", "err", err) + return false, err + } + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, actionType, "*"); !ok { + return false, nil + } + return true, nil + //RBAC enforcer ends here + + case bean2.HelmAppType: + appIdentifier, err := handler.helmAppService.DecodeAppId(request.AppId) + if err != nil { + handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) + return false, err + } + //setting appIdentifier value in request + request.AppIdentifier = appIdentifier + request.ClusterId = request.AppIdentifier.ClusterId + if request.DeploymentType == bean2.HelmInstalledType { + if err := handler.k8sApplicationService.ValidateResourceRequest(r.Context(), request.AppIdentifier, request.K8sRequest); err != nil { + return false, err + } + } else if request.DeploymentType == bean2.ArgoInstalledType { + //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree + } + // RBAC enforcer applying for Helm App + rbacObject, rbacObject2 = handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(request.AppIdentifier.ClusterId, request.AppIdentifier.Namespace, request.AppIdentifier.ReleaseName) + ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, actionType, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, actionType, rbacObject2) + if !ok { + return false, nil + } + return true, nil + // RBAC enforcer Ends + case bean2.DevtronAppType: + devtronAppIdentifier, err := handler.k8sApplicationService.DecodeDevtronAppId(request.AppId) + if err != nil { + handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) + return false, err + } + //setting devtronAppIdentifier value in request + request.DevtronAppIdentifier = devtronAppIdentifier + request.ClusterId = request.DevtronAppIdentifier.ClusterId + if request.DeploymentType == bean2.HelmInstalledType { + //TODO Implement ResourceRequest Validation for Helm Installed Devtron APPs + } else if request.DeploymentType == bean2.ArgoInstalledType { + //TODO Implement ResourceRequest Validation for ArgoCD Installed APPs From ResourceTree + } + // RBAC enforcer applying for Devtron App + envObject = handler.enforcerUtil.GetEnvRBACNameByAppId(request.DevtronAppIdentifier.AppId, request.DevtronAppIdentifier.EnvId) + hasReadAccessForEnv := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, actionType, envObject) + if !hasReadAccessForEnv { + return false, nil + } + // RBAC enforcer Ends + return true, nil + case bean2.FluxAppType: + // For flux app resource + appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(request.AppId) + if err != nil { + handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) + return false, err + } + //setting fluxAppIdentifier value in request + request.ExternalFluxAppIdentifier = appIdentifier + request.ClusterId = appIdentifier.ClusterId + valid, err := handler.k8sApplicationService.ValidateFluxResourceRequest(r.Context(), request.ExternalFluxAppIdentifier, request.K8sRequest) + if err != nil || !valid { + handler.logger.Errorw("error in validating resource request", "err", err) + return false, err + } + //RBAC enforcer starts here + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, actionType, "*"); !ok { + return false, nil + } + return true, nil + //RBAC enforcer ends here + default: + handler.logger.Errorw("appType not recognized", "appType", request.AppType) + return false, errors.New("appType not founded in request") + } +} diff --git a/api/k8s/application/k8sApplicationRouter.go b/api/k8s/application/k8sApplicationRouter.go index 911a6eb998..a05b2ca3dc 100644 --- a/api/k8s/application/k8sApplicationRouter.go +++ b/api/k8s/application/k8sApplicationRouter.go @@ -38,7 +38,9 @@ func (impl *K8sApplicationRouterImpl) InitK8sApplicationRouter(k8sAppRouter *mux k8sAppRouter.Path("/resource/rotate").Queries("appId", "{appId}"). HandlerFunc(impl.k8sApplicationRestHandler.RotatePod).Methods("POST") - k8sAppRouter.Path("/resource/urls").Queries("appId", "{appId}"). + k8sAppRouter.Path("/resource/urls"). + Queries("appId", "{appId}"). + Queries("appType", "{appType}"). //introduced for the k8s resource urls HandlerFunc(impl.k8sApplicationRestHandler.GetHostUrlsByBatch).Methods("GET") k8sAppRouter.Path("/resource"). diff --git a/api/restHandler/app/appList/AppListingRestHandler.go b/api/restHandler/app/appList/AppListingRestHandler.go index ee8441de94..73a6226fa3 100644 --- a/api/restHandler/app/appList/AppListingRestHandler.go +++ b/api/restHandler/app/appList/AppListingRestHandler.go @@ -977,7 +977,7 @@ func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWrite return } // valid batch requests, only valid requests will be sent for batch processing - validRequests := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTree, appDetail, "", []string{k8sCommonBean.ServiceKind, k8sCommonBean.IngressKind}) + validRequests := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTree, appDetail, "", []string{k8sCommonBean.ServiceKind, k8sCommonBean.IngressKind}, "") if len(validRequests) == 0 { handler.logger.Error("neither service nor ingress found for", "appId", appIdParam, "envId", envIdParam, "installedAppId", installedAppIdParam) common.WriteJsonResp(w, err, nil, http.StatusNoContent) @@ -1148,7 +1148,7 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter }, } clusterIdString := strconv.Itoa(cdPipeline.Environment.ClusterId) - validRequest := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTree, k8sAppDetail, clusterIdString, []string{k8sCommonBean.ServiceKind, k8sCommonBean.EndpointsKind, k8sCommonBean.IngressKind}) + validRequest := handler.k8sCommonService.FilterK8sResources(r.Context(), resourceTree, k8sAppDetail, clusterIdString, []string{k8sCommonBean.ServiceKind, k8sCommonBean.EndpointsKind, k8sCommonBean.IngressKind}, "") resp, err := handler.k8sCommonService.GetManifestsByBatch(r.Context(), validRequest) if err != nil { handler.logger.Errorw("error in getting manifest by batch", "err", err, "clusterId", clusterIdString) diff --git a/api/router/router.go b/api/router/router.go index 95bbeade9a..8902c53caf 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -31,6 +31,7 @@ import ( "github.com/devtron-labs/devtron/api/deployment" "github.com/devtron-labs/devtron/api/devtronResource" "github.com/devtron-labs/devtron/api/externalLink" + fluxApplication2 "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/application" @@ -115,6 +116,7 @@ type MuxRouter struct { ciTriggerCron cron.CiTriggerCron infraConfigRouter infraConfig.InfraConfigRouter argoApplicationRouter argoApplication.ArgoApplicationRouter + fluxApplicationRouter fluxApplication2.FluxApplicationRouter devtronResourceRouter devtronResource.DevtronResourceRouter } @@ -146,7 +148,9 @@ func NewMuxRouter(logger *zap.SugaredLogger, proxyRouter proxy.ProxyRouter, infraConfigRouter infraConfig.InfraConfigRouter, argoApplicationRouter argoApplication.ArgoApplicationRouter, - devtronResourceRouter devtronResource.DevtronResourceRouter) *MuxRouter { + devtronResourceRouter devtronResource.DevtronResourceRouter, + fluxApplicationRouter fluxApplication2.FluxApplicationRouter, + ) *MuxRouter { r := &MuxRouter{ Router: mux.NewRouter(), EnvironmentClusterMappingsRouter: EnvironmentClusterMappingsRouter, @@ -209,6 +213,7 @@ func NewMuxRouter(logger *zap.SugaredLogger, infraConfigRouter: infraConfigRouter, argoApplicationRouter: argoApplicationRouter, devtronResourceRouter: devtronResourceRouter, + fluxApplicationRouter: fluxApplicationRouter, } return r } @@ -416,4 +421,7 @@ func (r MuxRouter) Init() { argoApplicationRouter := r.Router.PathPrefix("/orchestrator/argo-application").Subrouter() r.argoApplicationRouter.InitArgoApplicationRouter(argoApplicationRouter) + + fluxApplicationRouter := r.Router.PathPrefix("/orchestrator/flux-application").Subrouter() + r.fluxApplicationRouter.InitFluxApplicationRouter(fluxApplicationRouter) } diff --git a/cmd/external-app/router.go b/cmd/external-app/router.go index 27da8cd83e..972695fb36 100644 --- a/cmd/external-app/router.go +++ b/cmd/external-app/router.go @@ -30,6 +30,7 @@ import ( "github.com/devtron-labs/devtron/api/cluster" "github.com/devtron-labs/devtron/api/dashboardEvent" "github.com/devtron-labs/devtron/api/externalLink" + "github.com/devtron-labs/devtron/api/fluxApplication" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/k8s/application" "github.com/devtron-labs/devtron/api/k8s/capacity" @@ -82,6 +83,7 @@ type MuxRouter struct { appRouter app.AppRouterEAMode rbacRoleRouter user.RbacRoleRouter argoApplicationRouter argoApplication.ArgoApplicationRouter + fluxApplicationRouter fluxApplication.FluxApplicationRouter } func NewMuxRouter( @@ -113,7 +115,7 @@ func NewMuxRouter( userTerminalAccessRouter terminal.UserTerminalAccessRouter, attributesRouter router.AttributesRouter, appRouter app.AppRouterEAMode, - rbacRoleRouter user.RbacRoleRouter, argoApplicationRouter argoApplication.ArgoApplicationRouter, + rbacRoleRouter user.RbacRoleRouter, argoApplicationRouter argoApplication.ArgoApplicationRouter, fluxApplicationRouter fluxApplication.FluxApplicationRouter, ) *MuxRouter { r := &MuxRouter{ Router: mux.NewRouter(), @@ -148,6 +150,7 @@ func NewMuxRouter( appRouter: appRouter, rbacRoleRouter: rbacRoleRouter, argoApplicationRouter: argoApplicationRouter, + fluxApplicationRouter: fluxApplicationRouter, } return r } @@ -283,4 +286,6 @@ func (r *MuxRouter) Init() { argoApplicationRouter := r.Router.PathPrefix("/orchestrator/argo-application").Subrouter() r.argoApplicationRouter.InitArgoApplicationRouter(argoApplicationRouter) + fluxApplicationRouter := r.Router.PathPrefix("/orchestrator/flux-application").Subrouter() + r.fluxApplicationRouter.InitFluxApplicationRouter(fluxApplicationRouter) } diff --git a/cmd/external-app/wire.go b/cmd/external-app/wire.go index b7df2f2a5f..6f23ffdf64 100644 --- a/cmd/external-app/wire.go +++ b/cmd/external-app/wire.go @@ -37,6 +37,7 @@ import ( "github.com/devtron-labs/devtron/api/connector" "github.com/devtron-labs/devtron/api/dashboardEvent" "github.com/devtron-labs/devtron/api/externalLink" + "github.com/devtron-labs/devtron/api/fluxApplication" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/k8s" "github.com/devtron-labs/devtron/api/module" @@ -114,6 +115,7 @@ func InitializeApp() (*App, error) { gitOps.GitOpsEAWireSet, providerConfig.DeploymentProviderConfigWireSet, argoApplication.ArgoApplicationWireSet, + fluxApplication.FluxApplicationWireSet, NewApp, NewMuxRouter, util.NewHttpClient, diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 4734f0cf48..72533cab86 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run github.com/google/wire/cmd/wire +//go:generate go run -mod=mod github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject @@ -26,6 +26,7 @@ import ( "github.com/devtron-labs/devtron/api/connector" "github.com/devtron-labs/devtron/api/dashboardEvent" externalLink2 "github.com/devtron-labs/devtron/api/externalLink" + fluxApplication2 "github.com/devtron-labs/devtron/api/fluxApplication" client2 "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/api/helm-app/service" @@ -83,6 +84,7 @@ import ( "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/deployment/providerConfig" "github.com/devtron-labs/devtron/pkg/externalLink" + "github.com/devtron-labs/devtron/pkg/fluxApplication" "github.com/devtron-labs/devtron/pkg/genericNotes" repository6 "github.com/devtron-labs/devtron/pkg/genericNotes/repository" k8s2 "github.com/devtron-labs/devtron/pkg/k8s" @@ -197,8 +199,8 @@ func InitializeApp() (*App, error) { userAuthServiceImpl := user.NewUserAuthServiceImpl(userAuthRepositoryImpl, sessionManager, loginService, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, userServiceImpl) teamServiceImpl := team.NewTeamServiceImpl(sugaredLogger, teamRepositoryImpl, userAuthServiceImpl) clusterRepositoryImpl := repository2.NewClusterRepositoryImpl(db, sugaredLogger) - v := informer.NewGlobalMapClusterNamespace() - k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v, k8sServiceImpl) + syncMap := informer.NewGlobalMapClusterNamespace() + k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, syncMap, k8sServiceImpl) clusterServiceImpl := cluster.NewClusterServiceImpl(clusterRepositoryImpl, sugaredLogger, k8sServiceImpl, k8sInformerFactoryImpl, userAuthRepositoryImpl, userRepositoryImpl, roleGroupRepositoryImpl) appStatusRepositoryImpl := appStatus.NewAppStatusRepositoryImpl(db, sugaredLogger) environmentRepositoryImpl := repository2.NewEnvironmentRepositoryImpl(db, sugaredLogger, appStatusRepositoryImpl) @@ -290,9 +292,10 @@ func InitializeApp() (*App, error) { } deletePostProcessorImpl := service2.NewDeletePostProcessorImpl(sugaredLogger) appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, installedAppDBServiceImpl, appStoreDeploymentDBServiceImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, appRepositoryImpl, eaModeDeploymentServiceImpl, eaModeDeploymentServiceImpl, environmentServiceImpl, helmAppServiceImpl, installedAppVersionHistoryRepositoryImpl, environmentVariables, acdConfig, gitOpsConfigReadServiceImpl, deletePostProcessorImpl, appStoreValidatorImpl, deploymentConfigServiceImpl) - helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) + fluxApplicationServiceImpl := fluxApplication.NewFluxApplicationServiceImpl(sugaredLogger, helmAppServiceImpl, clusterServiceImpl, helmAppClientImpl, pumpImpl) + argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, helmUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) + helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig, fluxApplicationServiceImpl, argoApplicationServiceImpl) helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) - argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, helmUserServiceImpl, helmAppServiceImpl) k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImpl, argoApplicationServiceImpl) environmentRestHandlerImpl := cluster2.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceImpl, k8sServiceImpl, k8sCommonServiceImpl) environmentRouterImpl := cluster2.NewEnvironmentRouterImpl(environmentRestHandlerImpl) @@ -301,13 +304,13 @@ func InitializeApp() (*App, error) { ephemeralContainersRepositoryImpl := repository2.NewEphemeralContainersRepositoryImpl(db, transactionUtilImpl) ephemeralContainerServiceImpl := cluster.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImpl, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationServiceImpl) - k8sApplicationServiceImpl, err := application.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImpl, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl) + k8sApplicationServiceImpl, err := application.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImpl, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl, fluxApplicationServiceImpl) if err != nil { return nil, err } ciPipelineRepositoryImpl := pipelineConfig.NewCiPipelineRepositoryImpl(db, sugaredLogger, transactionUtilImpl) enforcerUtilImpl := rbac.NewEnforcerUtilImpl(sugaredLogger, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, clusterRepositoryImpl, enforcerImpl) - k8sApplicationRestHandlerImpl := application2.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables) + k8sApplicationRestHandlerImpl := application2.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables, fluxApplicationServiceImpl, argoApplicationServiceImpl) k8sApplicationRouterImpl := application2.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, attributesServiceImpl) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) @@ -424,7 +427,9 @@ func InitializeApp() (*App, error) { rbacRoleRouterImpl := user2.NewRbacRoleRouterImpl(sugaredLogger, validate, rbacRoleRestHandlerImpl) argoApplicationRestHandlerImpl := argoApplication2.NewArgoApplicationRestHandlerImpl(argoApplicationServiceImpl, sugaredLogger, enforcerImpl) argoApplicationRouterImpl := argoApplication2.NewArgoApplicationRouterImpl(argoApplicationRestHandlerImpl) - muxRouter := NewMuxRouter(sugaredLogger, ssoLoginRouterImpl, teamRouterImpl, userAuthRouterImpl, userRouterImpl, clusterRouterImpl, dashboardRouterImpl, helmAppRouterImpl, environmentRouterImpl, k8sApplicationRouterImpl, chartRepositoryRouterImpl, appStoreDiscoverRouterImpl, appStoreValuesRouterImpl, appStoreDeploymentRouterImpl, chartProviderRouterImpl, dockerRegRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, userAttributesRouterImpl, telemetryRouterImpl, userTerminalAccessRouterImpl, attributesRouterImpl, appRouterEAModeImpl, rbacRoleRouterImpl, argoApplicationRouterImpl) + fluxApplicationRestHandlerImpl := fluxApplication2.NewFluxApplicationRestHandlerImpl(fluxApplicationServiceImpl, sugaredLogger, enforcerImpl) + fluxApplicationRouterImpl := fluxApplication2.NewFluxApplicationRouterImpl(fluxApplicationRestHandlerImpl) + muxRouter := NewMuxRouter(sugaredLogger, ssoLoginRouterImpl, teamRouterImpl, userAuthRouterImpl, userRouterImpl, clusterRouterImpl, dashboardRouterImpl, helmAppRouterImpl, environmentRouterImpl, k8sApplicationRouterImpl, chartRepositoryRouterImpl, appStoreDiscoverRouterImpl, appStoreValuesRouterImpl, appStoreDeploymentRouterImpl, chartProviderRouterImpl, dockerRegRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, userAttributesRouterImpl, telemetryRouterImpl, userTerminalAccessRouterImpl, attributesRouterImpl, appRouterEAModeImpl, rbacRoleRouterImpl, argoApplicationRouterImpl, fluxApplicationRouterImpl) mainApp := NewApp(db, sessionManager, muxRouter, telemetryEventClientImpl, posthogClient, sugaredLogger) return mainApp, nil } diff --git a/devtron-images.txt.source b/devtron-images.txt.source new file mode 100644 index 0000000000..778292ffed --- /dev/null +++ b/devtron-images.txt.source @@ -0,0 +1,39 @@ +quay.io/devtron/image-scanner:137872c2-141-23848 +quay.io/devtron/inception:473deaa4-185-21582 +quay.io/devtron/hyperion:291c4c75-280-23860 +public.ecr.aws/docker/library/redis:7.0.5-alpine +quay.io/argoproj/argocd:v2.5.2 +quay.io/argoproj/workflow-controller:v3.4.3 +quay.io/devtron/authenticator:e414faff-393-13273 +quay.io/devtron/bats:v1.4.1 +quay.io/devtron/busybox:1.31.1 +quay.io/devtron/chart-sync:5a1d0301-150-23845 +quay.io/devtron/curl:7.73.0 +quay.io/devtron/dashboard:5f95d187-690-23841 +quay.io/devtron/devtron-utils:dup-chart-repo-v1.1.0 +quay.io/devtron/devtron:291c4c75-434-23853 +quay.io/devtron/ci-runner:48aca9f4-138-23844 +quay.io/devtron/dex:v2.30.2 +quay.io/devtron/git-sensor:86e13283-200-23847 +quay.io/devtron/grafana:7.3.1 +quay.io/devtron/k8s-sidecar:1.1.0 +quay.io/devtron/k8s-utils:tutum-curl +quay.io/devtron/kubectl:latest +quay.io/devtron/kubelink:0dee6306-564-23843 +quay.io/devtron/kubewatch:850b40d5-419-23840 +quay.io/devtron/lens:56211042-333-23839 +quay.io/devtron/migrator:v4.16.2 +quay.io/devtron/nats-box +quay.io/devtron/nats-server-config-reloader:0.6.2 +quay.io/devtron/nats:2.9.3-alpine +quay.io/devtron/notifier:9639b1ab-372-23850 +quay.io/devtron/postgres:11.9 +quay.io/devtron/postgres_exporter:v0.10.1 +quay.io/devtron/prometheus-nats-exporter:0.9.0 +quay.io/devtron/minio:RELEASE.2021-02-14T04-01-33Z +quay.io/devtron/clair:4.3.6 +quay.io/devtron/postgres:11.9.0-debian-10-r26 +quay.io/devtron/postgres_exporter:v0.4.7 +quay.io/devtron/minio-mc:RELEASE.2021-02-14T04-28-06Z +quay.io/devtron/minideb:latest + diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 7412526613..2a55ffcad3 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -7,6 +7,7 @@ * [Install Devtron with CI/CD and GitOps (Argo CD)](setup/install/install-devtron-with-cicd-with-gitops.md) * [Install Devtron without Integrations](setup/install/install-devtron.md) * [Install Devtron on Minikube, Microk8s, K3s, Kind, Cloud VMs](setup/install/Install-devtron-on-Minikube-Microk8s-K3s-Kind.md) + * [Install Devtron on Airgapped Environment](setup/install/install-devtron-in-airgapped-environment.md) * [Demo on Popular Cloud Providers](setup/install/demo-tutorials.md) * [Backup for Disaster Recovery](setup/install/devtron-backup.md) * [Uninstall Devtron](setup/install/uninstall-devtron.md) @@ -24,7 +25,7 @@ * [Git Accounts](user-guide/global-configurations/git-accounts.md) * [Container/OCI Registry](user-guide/global-configurations/container-registries.md) * [Chart Repositories](user-guide/global-configurations/chart-repo.md) - * [Custom Charts](user-guide/global-configurations/custom-charts.md) + * [Deployment Charts](user-guide/global-configurations/deployment-charts.md) * [Authorization](user-guide/global-configurations/authorization/README.md) * [SSO Login Services](user-guide/global-configurations/sso-login.md) * [Google](user-guide/global-configurations/authorization/sso/google.md) diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md index 69402187cb..c219ea5bd1 100644 --- a/docs/reference/glossary.md +++ b/docs/reference/glossary.md @@ -64,9 +64,9 @@ Temporarily marking a node as unschedulable, preventing new pods from being assi CronJob is used to create Jobs on a repeating schedule. It is commonly used for running periodic tasks with no manual intervention. In Devtron, you can view a list of cronjobs by going to Resource Browser → (choose a cluster) → Workloads → CronJob. [Read More...](../user-guide/creating-application/deployment-template/job-and-cronjob.md#2.-cronjob) -### Custom Charts +### Deployment Charts -Devtron offers a variety of ready-made Helm charts for common tasks and functions. If you have a specific need that isn't met by these preconfigured charts, super-admins have the permission to upload their own custom charts. Once uploaded, these custom charts become accessible for use by all users on the Devtron platform. [Read More...](../user-guide/global-configurations/custom-charts.md) +Devtron offers a variety of ready-made Helm charts for common tasks and functions. If you have a specific need that isn't met by these preconfigured charts, super-admins have the permission to upload their own charts. Once uploaded, these charts become accessible for use by all users on the Devtron platform. [Read More...](../user-guide/global-configurations/deployment-charts.md) ### DaemonSet diff --git a/docs/setup/install/install-devtron-in-airgapped-environment.md b/docs/setup/install/install-devtron-in-airgapped-environment.md new file mode 100644 index 0000000000..8d705fb77a --- /dev/null +++ b/docs/setup/install/install-devtron-in-airgapped-environment.md @@ -0,0 +1,245 @@ +# Devtron Installation in an Airgapped Environment + +## Introduction + +In certain scenarios, you may need to deploy Devtron to a Kubernetes cluster that isn’t connected to the internet. Such air-gapped environments are used for various reasons, particularly in industries with strict regulatory requirements like healthcare, banking, and finance. This is because air-gapped environments aren't exposed to the public internet; therefore, they create a controlled and secure space for handling sensitive data and operations. + +### Prerequisites + +1. Install `podman` or `docker` on the VM from where you're executing the installation commands. +2. Clone the Devtron Helm chart: + + ```bash + git clone https://github.com/devtron-labs/devtron.git + cd devtron + ``` + +3. Set the values of `TARGET_REGISTRY`, `TARGET_REGISTRY_USERNAME`, and `TARGET_REGISTRY_TOKEN`. This registry should be accessible from the VM where you are running the cloning script and the K8s cluster where you’re installing Devtron. + +{% hint style="warning" %} +### Note +If you are using Docker, the TARGET_REGISTRY should be in the format `docker.io/` +{% endhint %} + +--- + +## Docker Instructions + +### Platform Selection + +#### For Linux/amd64 + + ```bash + export PLATFORM="linux/amd64" + ``` +#### For Linux/arm64 + + ```bash + export PLATFORM="linux/arm64" + ``` + + + +1. Set the environment variables + + ```bash + # Set the source registry URL + export SOURCE_REGISTRY="quay.io/devtron" + + # Set the target registry URL, username, and token/password + export TARGET_REGISTRY="" + export TARGET_REGISTRY_USERNAME="" + export TARGET_REGISTRY_TOKEN="" + + # Set the source and target image file names with default values if not already set + SOURCE_IMAGES_LIST="${SOURCE_IMAGES_LIST:=devtron-images.txt.source}" + TARGET_IMAGES_LIST="${TARGET_IMAGES_LIST:=devtron-images.txt.target}" + ``` + +2. Log in to the target Docker registry + + ```bash + docker login -u $TARGET_REGISTRY_USERNAME -p $TARGET_REGISTRY_TOKEN $TARGET_REGISTRY + ``` + +3. Clone the images + + ```bash + while IFS= read -r source_image; do + # Check if the source image belongs to the quay.io/devtron registry + if [[ "$source_image" == quay.io/devtron/* ]]; then + # Replace the source registry with the target registry in the image name + target_image="${source_image/quay.io\/devtron/$TARGET_REGISTRY}" + + # Check if the source image belongs to the quay.io/argoproj registry + elif [[ "$source_image" == quay.io/argoproj/* ]]; then + # Replace the source registry with the target registry in the image name + target_image="${source_image/quay.io\/argoproj/$TARGET_REGISTRY}" + + # Check if the source image belongs to the public.ecr.aws/docker/library registry + elif [[ "$source_image" == public.ecr.aws/docker/library/* ]]; then + # Replace the source registry with the target registry in the image name + target_image="${source_image/public.ecr.aws\/docker\/library/$TARGET_REGISTRY}" + fi + + # Pull the image from the source registry + docker pull --platform $PLATFORM $source_image + + # Tag the image with the new target registry name + docker tag $source_image $target_image + + # Push the image to the target registry + docker push $target_image + + # Output the updated image name + echo "Updated image: $target_image" + + # Append the new image name to the target image file + echo "$target_image" >> "$TARGET_IMAGES_LIST" + + done < "$SOURCE_IMAGES_LIST" + ``` +--- + +## Podman Instructions + +### For Multi-arch + +1. Set the environment variables + + ```bash + export SOURCE_REGISTRY="quay.io/devtron" + export SOURCE_REGISTRY_TOKEN=#Enter token provided by Devtron team + export TARGET_REGISTRY=#Enter target registry url + export TARGET_REGISTRY_USERNAME=#Enter target registry username + export TARGET_REGISTRY_TOKEN=#Enter target registry token/password + ``` + +2. Log in to the target Podman registry + + ```bash + podman login -u $TARGET_REGISTRY_USERNAME -p $TARGET_REGISTRY_TOKEN $TARGET_REGISTRY + ``` + +3. Clone the images + + ```bash + SOURCE_REGISTRY="quay.io/devtron" + TARGET_REGISTRY=${TARGET_REGISTRY} + SOURCE_IMAGES_FILE_NAME="${SOURCE_IMAGES_FILE_NAME:=devtron-images.txt.source}" + TARGET_IMAGES_FILE_NAME="${TARGET_IMAGES_FILE_NAME:=devtron-images.txt.target}" + + cp $SOURCE_IMAGES_FILE_NAME $TARGET_IMAGES_FILE_NAME + while read source_image; do + if [[ "$source_image" == *"workflow-controller:"* || "$source_image" == *"argoexec:"* || "$source_image" == *"argocd:"* ]] + then + SOURCE_REGISTRY="quay.io/argoproj" + sed -i "s|${SOURCE_REGISTRY}|${TARGET_REGISTRY}|g" $TARGET_IMAGES_FILE_NAME + elif [[ "$source_image" == *"redis:"* ]] + then + SOURCE_REGISTRY="public.ecr.aws/docker/library" + sed -i "s|${SOURCE_REGISTRY}|${TARGET_REGISTRY}|g" $TARGET_IMAGES_FILE_NAME + else + SOURCE_REGISTRY="quay.io/devtron" + sed -i "s|${SOURCE_REGISTRY}|${TARGET_REGISTRY}|g" $TARGET_IMAGES_FILE_NAME + fi + done <$SOURCE_IMAGES_FILE_NAME + echo "Target Images file finalized" + + while read -r -u 3 source_image && read -r -u 4 target_image ; do + echo "Pushing $source_image $target_image" + podman manifest create $source_image + podman manifest add $source_image $source_image --all + podman manifest push $source_image $target_image --all + done 3<"$SOURCE_IMAGES_FILE_NAME" 4<"$TARGET_IMAGES_FILE_NAME" + ``` + +--- + +## Devtron Installation + +Before starting, ensure you have created an image pull secret for your registry if authentication is required. + +1. Create the namespace (if not already created) + ```bash + kubectl create ns devtroncd + ``` + +2. Create the Docker registry secret + ```bash + kubectl create secret docker-registry devtron-imagepull \ + --namespace devtroncd \ + --docker-server=$TARGET_REGISTRY \ + --docker-username=$TARGET_REGISTRY_USERNAME \ + --docker-password=$TARGET_REGISTRY_TOKEN + ``` + If you are installing Devtron with the CI/CD module or using Argo CD, create the secret in the following namespaces else, you can skip this step-: + ```bash + kubectl create secret docker-registry devtron-imagepull \ + --namespace devtron-cd \ + --docker-server=$TARGET_REGISTRY \ + --docker-username=$TARGET_REGISTRY_USERNAME \ + --docker-password=$TARGET_REGISTRY_TOKEN + kubectl create secret docker-registry devtron-imagepull \ + --namespace devtron-ci \ + --docker-server=$TARGET_REGISTRY \ + --docker-username=$TARGET_REGISTRY_USERNAME \ + --docker-password=$TARGET_REGISTRY_TOKEN + kubectl create secret docker-registry devtron-imagepull \ + --namespace argo \ + --docker-server=$TARGET_REGISTRY \ + --docker-username=$TARGET_REGISTRY_USERNAME \ + --docker-password=$TARGET_REGISTRY_TOKEN + ``` + +3. Navigate to the Devtron Helm chart directory + ```bash + cd charts/devtron + ``` + + +### Install Devtron without any Integration + +Use the below command to install Devtron without any Integrations + +1. Without `imagePullSecrets`: + ```bash + helm install devtron . -n devtroncd --set global.containerRegistry="$TARGET_REGISTRY" + ``` + +2. With `imagePullSecrets`: + ```bash + helm install devtron . -n devtroncd --set global.containerRegistry="$TARGET_REGISTRY" --set global.imagePullSecrets[0].name=devtron-imagepull + ``` + +### Installing Devtron with CI/CD Mode +Use the below command to install Devtron with only the CI/CD module + +1. Without `imagePullSecrets`: + ```bash + helm install devtron . -n devtroncd --set installer.modules={cicd} --set global.containerRegistry="$TARGET_REGISTRY" + ``` + +2. With `imagePullSecrets`: + ```bash + helm install devtron . -n devtroncd --set installer.modules={cicd} --set global.containerRegistry="$TARGET_REGISTRY" --set global.imagePullSecrets[0].name=devtron-imagepull + ``` + +### Install Devtron with CICD Mode including Argocd + +Use the below command to install Devtron with the CI/CD module and Argo CD + +1. Without `imagePullSecrets`: + ```bash + helm install devtron . --create-namespace -n devtroncd --set installer.modules={cicd} --set argo-cd.enabled=true --set global.containerRegistry="$TARGET_REGISTRY" --set argo-cd.global.image.repository="${TARGET_REGISTRY}/argocd" --set argo-cd.redis.image.repository="${TARGET_REGISTRY}/redis" + ``` + +2. With `imagePullSecrets`: + ```bash + helm install devtron . --create-namespace -n devtroncd --set installer.modules={cicd} --set argo-cd.enabled=true --set global.containerRegistry="$TARGET_REGISTRY" --set argo-cd.global.image.repository="${TARGET_REGISTRY}/argocd" --set argo-cd.redis.image.repository="${TARGET_REGISTRY}/redis" --set global.imagePullSecrets[0].name=devtron-imagepull + ``` + +--- + +## Next Steps +After installation, refer [Devtron installation documentation](https://docs.devtron.ai/install/install-devtron-with-cicd-with-gitops#devtron-dashboard) for further steps, including obtaining the dashboard URL and the admin password. diff --git a/docs/user-guide/creating-application/deployment-template.md b/docs/user-guide/creating-application/deployment-template.md index c3e7438236..ab117b9a3c 100644 --- a/docs/user-guide/creating-application/deployment-template.md +++ b/docs/user-guide/creating-application/deployment-template.md @@ -23,7 +23,7 @@ Users need to have [Admin role](../user-guide/global-configurations/authorizatio {% hint style="warning" %} ### Note -After you select and save a chart type for a given application, you won't be able to change it later. Make sure to choose the correct chart type before saving. You can select a chart from [Devtron Charts](#from-devtron-charts) or [Custom Charts](#from-custom-charts). +After you select and save a chart type for a given application, you won't be able to change it later. Make sure to choose the correct chart type before saving. You can select a chart from [Devtron Charts](#from-devtron-charts) or other [Deployment Charts](#from-deployment-charts). {% endhint %} ### From Devtron Charts @@ -37,10 +37,10 @@ You can select a default deployment chart from the following options: ![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/deployment-template/select-devtron-chart.gif) -### From Custom Charts +### From Deployment Charts {% hint style="warning" %} -This option will be available only if a custom chart exists. If it doesn't, a user with `super admin` permission may upload one in [Global Configurations → Custom Charts](../global-configurations/custom-charts.md). +This option will be available only if a custom chart exists. If it doesn't, a user with `super admin` permission may upload one in [Global Configurations → Deployment Charts](../global-configurations/deployment-charts.md). {% endhint %} You can select an available custom chart as shown below. You can also view the description of the custom charts in the list. @@ -110,20 +110,26 @@ Click **Save Changes**. If you want to do additional configurations, then click {% hint style="warning" %} ### Who Can Perform This Action? -Superadmin can define and apply custom deployment schema using API +Superadmin can define and apply custom deployment schema. {% endhint %} By default, the `Basic (GUI)` section comes with multiple predefined fields as seen earlier [in the table](#2-basic-configuration). However, if you wish to display a different set of fields to your team, you can modify the whole section as per your requirement. -{% embed url="https://www.youtube.com/watch?v=09VP1I-WvUs" caption="JSON-driven Deployment Schema" %} - This is useful in scenarios where: * Your team members find it difficult to understand and edit the [Advanced (YAML)](#3-advanced-yaml) section. * You frequently edit certain fields in Advanced (YAML), which you expect to remain easily accessible in Basic (GUI) section. * You don't require some fields in Basic (GUI) section. * You need the autonomy to keep the Basic (GUI) unique for applications/clusters/environments/charts, or display the same Basic (GUI) everywhere. -This is possible by passing a custom JSON (deployment schema) of your choice through the following API. You may need to run the API with the `POST` method if you are doing it for the first time. +{% hint style="info" %} +There are two ways you can customize the Basic GUI, use any one of the following: +1. From [Deployment Charts](../global-configurations/deployment-charts.md#editing-gui-schema-of-deployment-charts) section +2. Using APIs (explained below) +{% endhint %} + +{% embed url="https://www.youtube.com/watch?v=09VP1I-WvUs" caption="JSON-driven Deployment Schema" %} + +You can pass a custom JSON (deployment schema) of your choice through the following API. You may need to run the API with the `POST` method if you are doing it for the first time. ``` PUT {{DEVTRON_BASEURL}}/orchestrator/deployment/template/schema diff --git a/docs/user-guide/global-configurations/README.md b/docs/user-guide/global-configurations/README.md index 488ed2328b..6a7aa4cf29 100644 --- a/docs/user-guide/global-configurations/README.md +++ b/docs/user-guide/global-configurations/README.md @@ -18,7 +18,7 @@ Before you start creating an application, we recommend to provide basic informat [Chart Repositories](chart-repo.md) -[Custom Charts](custom-charts.md) +[Deployment Charts](deployment-charts.md) [Authorization](authorization/README.md) diff --git a/docs/user-guide/global-configurations/custom-charts.md b/docs/user-guide/global-configurations/deployment-charts.md similarity index 68% rename from docs/user-guide/global-configurations/custom-charts.md rename to docs/user-guide/global-configurations/deployment-charts.md index 18fefc8759..256e105cc3 100644 --- a/docs/user-guide/global-configurations/custom-charts.md +++ b/docs/user-guide/global-configurations/deployment-charts.md @@ -1,4 +1,4 @@ -# Custom Charts +# Deployment Charts Devtron includes predefined helm charts that cover the majority of use cases. For any use case not addressed by the default helm charts, you can upload your own helm chart and use it as a custom chart in Devtron. @@ -8,7 +8,7 @@ For any use case not addressed by the default helm charts, you can upload your o > A super admin can upload multiple versions of a custom helm chart. -![Custom charts](https://devtron-public-asset.s3.us-east-2.amazonaws.com/custom-charts/custom-charts-lists.png) +![Figure 1: Deployment Charts](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/gc-deployment-charts.jpg) ## Prerequisites @@ -99,7 +99,9 @@ helm package my-custom-chart The above command will create a `my-custom-chart-0.1.0.tgz` file. -## Uploading a custom chart +--- + +## Uploading a Deployment Chart > A custom chart can only be uploaded by a super admin. @@ -142,21 +144,73 @@ The following are the validation results: ![Already exists](https://devtron-public-asset.s3.us-east-2.amazonaws.com/custom-charts/List+-+Empty-1.png) -## View the custom charts +--- + +## Viewing Deployment Charts > All users can view the custom charts. -To view a list of available custom charts, go to **Global Configurations > Custom charts** page. +To view the list of available custom charts, go to **Global Configurations → Deployment Charts** page. * The charts can be searched with their name, version, or description. * New [custom charts can be uploaded](#uploading-a-custom-chart) by selecting **Upload chart**. -![Custom charts](https://devtron-public-asset.s3.us-east-2.amazonaws.com/custom-charts/custom-charts-lists.png) +![Custom charts](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/upload-custom-chart.jpg) + +--- -## Use the custom chart in an application +## Using Deployment Chart in Application The custom charts can be used from the [Deployment Template](../creating-application/deployment-template.md) section. > **Info**: > > The deployment strategy for a custom chart is fetched from the custom chart template and cannot be configured in the [CD pipeline](../creating-application/workflow/cd-pipeline.md#deployment-strategies). + +--- + +## Editing GUI Schema of Deployment Charts [![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/elements/EnterpriseTag.svg)](https://devtron.ai/pricing) + +{% hint style="warning" %} +### Who Can Perform This Action? +Only superadmins can edit the GUI schema of deployment charts. +{% endhint %} + +{% hint style="info" %} +### Reference +This section is an extension of [Customize Basic GUI](../creating-application/deployment-template.md#customize-basic-gui) feature within **App Configuration** → **Base Deployment Template**. Refer the document to know more about the significance of having a customizable GUI schema for your deployment templates. +{% endhint %} + +You can edit the GUI schema of both the deployment charts: +1. Charts provided by Devtron (*Deployment*, *Job & CronJob*, *Rollout Deployment*, and *StatefulSet*) +2. Custom charts uploaded by you + +### Tutorial + +{% embed url="https://www.youtube.com/watch?v=93tGIsM1qC8" caption="JSON-driven Deployment Schema" %} + +### Steps + +In this example, we will edit the Deployment chart type provided by Devtron. + +1. Click the edit button next to the chart as shown below. + + ![Edit GUI Schema Button](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/edit-chart-schema.jpg) + +2. A GUI schema is available for you to edit in case of Devtron charts. In case of custom charts, you may have to define a GUI schema yourself. To know how to create such GUI schema, refer [RJSF JSON Schema Tool](https://rjsf-team.github.io/react-jsonschema-form/). + + ![Editable Schema](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/gui-schema.jpg) + +3. You may start editing the schema by excluding existing fields/objects or including more of them. Click the **Refer YAML** button to view all the supported fields. + + ![Refer YAML Button](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/refer-yaml.gif) + +4. While editing the schema, you may use the **Preview GUI** option for a real-time preview of your changes. + + ![Preview GUI Button](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/preview-gui.gif) + +5. Click **Save Changes**. + + ![Save Changes](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/deployment-charts/save-changes.jpg) + +Next, if you go to **App Configuration** → **Base Deployment Template**, you will be able to see the deployment template fields (in Basic GUI) as per your customized schema. \ No newline at end of file diff --git a/env_gen.md b/env_gen.md index 6e3c3e4f9f..187544e5ce 100644 --- a/env_gen.md +++ b/env_gen.md @@ -6,7 +6,7 @@ | ACD_NAMESPACE | devtroncd | | | ACD_PASSWORD | | | | ACD_USERNAME | admin | | - | APP | orchestrator | | + | APP | orchestrator | Application name | | APP_SYNC_IMAGE | quay.io/devtron/chart-sync:1227622d-132-3775 | | | APP_SYNC_JOB_RESOURCES_OBJ | | | | APP_SYNC_SERVICE_ACCOUNT | chart-sync | | @@ -231,6 +231,7 @@ | SCOPED_VARIABLE_HANDLE_PRIMITIVES | false | | | SCOPED_VARIABLE_NAME_REGEX | ^[a-zA-Z][a-zA-Z0-9_-]{0,62}[a-zA-Z0-9]$ | | | SHOW_DOCKER_BUILD_ARGS | true | | + | SKIP_CI_JOB_BUILD_CACHE_PUSH_PULL | false | | | SKIP_CREATING_ECR_REPO | false | | | SOCKET_DISCONNECT_DELAY_SECONDS | 5 | | | SOCKET_HEARTBEAT_SECONDS | 25 | | diff --git a/fetchAllEnv/fetchAllEnv.go b/fetchAllEnv/fetchAllEnv.go index 86585d4385..6df7dcc317 100644 --- a/fetchAllEnv/fetchAllEnv.go +++ b/fetchAllEnv/fetchAllEnv.go @@ -36,9 +36,10 @@ type EnvField struct { } const ( - envFieldTypeTag = "env" - envDefaultFieldTypeTag = "envDefault" - MARKDOWN_FILENAME = "env_gen.md" + envFieldTypeTag = "env" + envDefaultFieldTypeTag = "envDefault" + envDescriptionFieldTypeTag = "envDescription" + MARKDOWN_FILENAME = "env_gen.md" ) const MarkdownTemplate = ` @@ -97,14 +98,15 @@ func convertTagToStructTag(tag string) reflect.StructTag { return reflect.StructTag(strings.Split(tag, "`")[1]) } -func getEnvKeyAndValue(tag reflect.StructTag) (string, string) { +func getEnvKeyAndValue(tag reflect.StructTag) (string, string, string) { envKey := tag.Get(envFieldTypeTag) envValue := tag.Get(envDefaultFieldTypeTag) + envDescription := tag.Get(envDescriptionFieldTypeTag) // check if there exist any value provided in env for this field if value, ok := os.LookupEnv(envKey); ok { envValue = value } - return envKey, envValue + return envKey, envValue, envDescription } func processGoFile(filePath string, allFields *[]EnvField, uniqueKeys *map[string]bool) error { @@ -122,13 +124,14 @@ func processGoFile(filePath string, allFields *[]EnvField, uniqueKeys *map[strin for _, field := range structType.Fields.List { if field.Tag != nil { strippedTags := convertTagToStructTag(field.Tag.Value) - envKey, envValue := getEnvKeyAndValue(strippedTags) + envKey, envValue, envDescription := getEnvKeyAndValue(strippedTags) if len(envKey) == 0 || (*uniqueKeys)[envKey] { continue } *allFields = append(*allFields, EnvField{ - Env: envKey, - EnvValue: envValue, + Env: envKey, + EnvValue: envValue, + EnvDescription: envDescription, }) (*uniqueKeys)[envKey] = true } diff --git a/go.mod b/go.mod index d86e38ff10..3ebbc979a9 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 - github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a + github.com/devtron-labs/common-lib v0.0.25-0.20240812113340-f14be466613d github.com/devtron-labs/go-bitbucket v0.9.60-beta github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80 github.com/evanphx/json-patch v5.7.0+incompatible diff --git a/go.sum b/go.sum index a3a440988a..aafbebf99a 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 h1:2+Q7Jdhpo/uMiaQiZZzAh+ZX7wEJIFuMFG6DEiMuo64= github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8/go.mod h1:702R6WIf5y9UzKGoCGxQ+x3l5Ws+l0fXg2xlCpSGFZI= -github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a h1:VebYW3ZIz85sZedsG1wRAaV3V4B2Bx26XXpG8T9VfAA= -github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a/go.mod h1:a7aCClaxYfnyYEENSe1RnkQCeW2AwmCAPYsuvgk0aW0= +github.com/devtron-labs/common-lib v0.0.25-0.20240812113340-f14be466613d h1:+iWXiVOyf9E0bcTia6x2sLFTM7xJc+9Z8q+BfbYr6eM= +github.com/devtron-labs/common-lib v0.0.25-0.20240812113340-f14be466613d/go.mod h1:a7aCClaxYfnyYEENSe1RnkQCeW2AwmCAPYsuvgk0aW0= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80 h1:xwbTeijNTf4/j1v+tSfwVqwLVnReas/NqEKeQHvSTys= diff --git a/internal/sql/repository/chartConfig/PipelineOverrideRepository.go b/internal/sql/repository/chartConfig/PipelineOverrideRepository.go index aba3d7554c..db8476d913 100644 --- a/internal/sql/repository/chartConfig/PipelineOverrideRepository.go +++ b/internal/sql/repository/chartConfig/PipelineOverrideRepository.go @@ -58,6 +58,7 @@ type PipelineConfigOverrideMetadata struct { type PipelineOverrideRepository interface { Save(*PipelineOverride) error + Update(pipelineOverride *PipelineOverride) error UpdateStatusByRequestIdentifier(requestId string, newStatus models.ChartStatus) (int, error) GetLatestConfigByRequestIdentifier(requestIdentifier string) (pipelineOverride *PipelineOverride, err error) GetLatestConfigByEnvironmentConfigOverrideId(envConfigOverrideId int) (pipelineOverride *PipelineOverride, err error) @@ -85,6 +86,10 @@ func (impl PipelineOverrideRepositoryImpl) Save(pipelineOverride *PipelineOverri return impl.dbConnection.Insert(pipelineOverride) } +func (impl PipelineOverrideRepositoryImpl) Update(pipelineOverride *PipelineOverride) error { + return impl.dbConnection.Update(pipelineOverride) +} + func (impl PipelineOverrideRepositoryImpl) UpdatePipelineMergedValues(ctx context.Context, tx *pg.Tx, id int, pipelineMergedValues string, userId int32) error { _, span := otel.Tracer("orchestrator").Start(ctx, "PipelineOverrideRepositoryImpl.UpdatePipelineMergedValues") defer span.End() diff --git a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go index c839a6ecdb..0187274fea 100644 --- a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go +++ b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go @@ -73,7 +73,7 @@ type CdWorkflowRepository interface { FetchAllCdStagesLatestEntity(pipelineIds []int) ([]*CdWorkflowStatus, error) FetchAllCdStagesLatestEntityStatus(wfrIds []int) ([]*CdWorkflowRunner, error) ExistsByStatus(status string) (bool, error) - + FetchEnvAllCdStagesLatestEntityStatus(wfrIds []int, envID int) ([]*CdWorkflowRunner, error) FetchArtifactsByCdPipelineId(pipelineId int, runnerType apiBean.WorkflowType, offset, limit int, searchString string) ([]CdWorkflowRunner, error) GetLatestTriggersOfHelmPipelinesStuckInNonTerminalStatuses(getPipelineDeployedWithinHours int) ([]*CdWorkflowRunner, error) FindLatestRunnerByPipelineIdsAndRunnerType(ctx context.Context, pipelineIds []int, runnerType apiBean.WorkflowType) ([]CdWorkflowRunner, error) @@ -685,8 +685,23 @@ func (impl *CdWorkflowRepositoryImpl) FetchAllCdStagesLatestEntity(pipelineIds [ func (impl *CdWorkflowRepositoryImpl) FetchAllCdStagesLatestEntityStatus(wfrIds []int) ([]*CdWorkflowRunner, error) { var wfrList []*CdWorkflowRunner - err := impl.dbConnection.Model(&wfrList).Column("cd_workflow_runner.*"). - Where("cd_workflow_runner.id in (?)", pg.In(wfrIds)).Select() + err := impl.dbConnection.Model(&wfrList). + Column("cd_workflow_runner.id", "cd_workflow_runner.status"). + Where("cd_workflow_runner.id in (?)", pg.In(wfrIds)). + Select() + return wfrList, err +} + +func (impl *CdWorkflowRepositoryImpl) FetchEnvAllCdStagesLatestEntityStatus(wfrIds []int, envID int) ([]*CdWorkflowRunner, error) { + var wfrList []*CdWorkflowRunner + query := ` + select wfr.id, wfr.status + from cd_workflow_runner wfr + inner join cd_workflow wf on wf.id = wfr.cd_workflow_id + inner join pipeline p on p.id = wf.pipeline_id + where p.environment_id = ? and wfr.id in (?) + ` + _, err := impl.dbConnection.Query(&wfrList, query, envID, pg.In(wfrIds)) return wfrList, err } diff --git a/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go b/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go index d8f4452635..29af259f51 100644 --- a/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go +++ b/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "github.com/devtron-labs/devtron/api/helm-app/gRPC" + repository2 "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" "github.com/devtron-labs/devtron/internal/util" clientErrors "github.com/devtron-labs/devtron/pkg/errors" "github.com/go-pg/pg" @@ -101,22 +102,61 @@ func (impl *InstalledAppResourceServiceImpl) findNotesForArgoApplication(install return notes, err } - installReleaseRequest := &gRPC.InstallReleaseRequest{ - ChartName: appStoreAppVersion.Name, - ChartVersion: appStoreAppVersion.Version, - ValuesYaml: installedAppVerison.ValuesYaml, - K8SVersion: k8sServerVersion.String(), - ChartRepository: &gRPC.ChartRepository{ + //TODO: common function for below logic for install/update/notes + var IsOCIRepo bool + var registryCredential *gRPC.RegistryCredential + var chartRepository *gRPC.ChartRepository + dockerRegistryId := appStoreAppVersion.AppStore.DockerArtifactStoreId + if dockerRegistryId != "" { + ociRegistryConfigs, err := impl.OCIRegistryConfigRepository.FindByDockerRegistryId(dockerRegistryId) + if err != nil { + impl.logger.Errorw("error in fetching oci registry config", "err", err) + return notes, err + } + var ociRegistryConfig *repository2.OCIRegistryConfig + for _, config := range ociRegistryConfigs { + if config.RepositoryAction == repository2.STORAGE_ACTION_TYPE_PULL || config.RepositoryAction == repository2.STORAGE_ACTION_TYPE_PULL_AND_PUSH { + ociRegistryConfig = config + break + } + } + IsOCIRepo = true + registryCredential = &gRPC.RegistryCredential{ + RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, + Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, + Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, + AwsRegion: appStoreAppVersion.AppStore.DockerArtifactStore.AWSRegion, + AccessKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, + SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + RegistryType: string(appStoreAppVersion.AppStore.DockerArtifactStore.RegistryType), + RepoName: appStoreAppVersion.AppStore.Name, + IsPublic: ociRegistryConfig.IsPublic, + Connection: appStoreAppVersion.AppStore.DockerArtifactStore.Connection, + RegistryName: appStoreAppVersion.AppStore.DockerArtifactStoreId, + RegistryCertificate: appStoreAppVersion.AppStore.DockerArtifactStore.Cert, + } + } else { + chartRepository = &gRPC.ChartRepository{ Name: appStoreAppVersion.AppStore.ChartRepo.Name, Url: appStoreAppVersion.AppStore.ChartRepo.Url, Username: appStoreAppVersion.AppStore.ChartRepo.UserName, Password: appStoreAppVersion.AppStore.ChartRepo.Password, AllowInsecureConnection: appStoreAppVersion.AppStore.ChartRepo.AllowInsecureConnection, - }, + } + } + + installReleaseRequest := &gRPC.InstallReleaseRequest{ + ChartName: appStoreAppVersion.Name, + ChartVersion: appStoreAppVersion.Version, + ValuesYaml: installedAppVerison.ValuesYaml, + K8SVersion: k8sServerVersion.String(), + ChartRepository: chartRepository, ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseNamespace: installedAppVerison.InstalledApp.Environment.Namespace, ReleaseName: installedAppVerison.InstalledApp.App.AppName, }, + IsOCIRepo: IsOCIRepo, + RegistryCredential: registryCredential, } clusterId := installedAppVerison.InstalledApp.Environment.ClusterId diff --git a/pkg/appStore/installedApp/service/FullMode/resource/ResourceTreeService.go b/pkg/appStore/installedApp/service/FullMode/resource/ResourceTreeService.go index 6c91f3f446..b1c9458864 100644 --- a/pkg/appStore/installedApp/service/FullMode/resource/ResourceTreeService.go +++ b/pkg/appStore/installedApp/service/FullMode/resource/ResourceTreeService.go @@ -29,6 +29,7 @@ import ( client "github.com/devtron-labs/devtron/api/helm-app/service" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/constants" + repository2 "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/appStatus" "github.com/devtron-labs/devtron/pkg/appStore/bean" @@ -72,6 +73,7 @@ type InstalledAppResourceServiceImpl struct { k8sApplicationService application3.K8sApplicationService K8sUtil k8s2.K8sService deploymentConfigurationService common.DeploymentConfigService + OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository } func NewInstalledAppResourceServiceImpl(logger *zap.SugaredLogger, @@ -83,7 +85,8 @@ func NewInstalledAppResourceServiceImpl(logger *zap.SugaredLogger, argoUserService argo.ArgoUserService, helmAppClient gRPC.HelmAppClient, helmAppService client.HelmAppService, appStatusService appStatus.AppStatusService, k8sCommonService k8s.K8sCommonService, k8sApplicationService application3.K8sApplicationService, K8sUtil k8s2.K8sService, - deploymentConfigurationService common.DeploymentConfigService) *InstalledAppResourceServiceImpl { + deploymentConfigurationService common.DeploymentConfigService, + OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository) *InstalledAppResourceServiceImpl { return &InstalledAppResourceServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -99,6 +102,7 @@ func NewInstalledAppResourceServiceImpl(logger *zap.SugaredLogger, k8sApplicationService: k8sApplicationService, K8sUtil: K8sUtil, deploymentConfigurationService: deploymentConfigurationService, + OCIRegistryConfigRepository: OCIRegistryConfigRepository, } } @@ -280,7 +284,7 @@ func (impl *InstalledAppResourceServiceImpl) fetchResourceTreeForACD(rctx contex }, } clusterIdString := strconv.Itoa(clusterId) - validRequest := impl.k8sCommonService.FilterK8sResources(rctx, resourceTree, k8sAppDetail, clusterIdString, []string{commonBean.ServiceKind, commonBean.EndpointsKind, commonBean.IngressKind}) + validRequest := impl.k8sCommonService.FilterK8sResources(rctx, resourceTree, k8sAppDetail, clusterIdString, []string{commonBean.ServiceKind, commonBean.EndpointsKind, commonBean.IngressKind}, "") response, err := impl.k8sCommonService.GetManifestsByBatch(rctx, validRequest) if err != nil { impl.logger.Errorw("error in getting manifest by batch", "err", err, "clusterId", clusterIdString) diff --git a/pkg/argoApplication/ArgoApplicationService.go b/pkg/argoApplication/ArgoApplicationService.go index eaafea66ef..e75272b84f 100644 --- a/pkg/argoApplication/ArgoApplicationService.go +++ b/pkg/argoApplication/ArgoApplicationService.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "github.com/devtron-labs/devtron/api/helm-app/gRPC" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/common-lib/utils/k8s" @@ -43,6 +44,8 @@ type ArgoApplicationService interface { clusterWithApplicationObject clusterRepository.Cluster, clusterServerUrlIdMap map[string]int) (*rest.Config, error) GetClusterConfigFromAllClusters(clusterId int) (*k8s.ClusterConfig, clusterRepository.Cluster, map[string]int, error) GetRestConfigForExternalArgo(ctx context.Context, clusterId int, externalArgoApplicationName string) (*rest.Config, error) + HibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) + UnHibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) } type ArgoApplicationServiceImpl struct { @@ -50,13 +53,14 @@ type ArgoApplicationServiceImpl struct { clusterRepository clusterRepository.ClusterRepository k8sUtil *k8s.K8sServiceImpl argoUserService argo.ArgoUserService + helmAppClient gRPC.HelmAppClient helmAppService service.HelmAppService } func NewArgoApplicationServiceImpl(logger *zap.SugaredLogger, clusterRepository clusterRepository.ClusterRepository, k8sUtil *k8s.K8sServiceImpl, - argoUserService argo.ArgoUserService, + argoUserService argo.ArgoUserService, helmAppClient gRPC.HelmAppClient, helmAppService service.HelmAppService) *ArgoApplicationServiceImpl { return &ArgoApplicationServiceImpl{ logger: logger, @@ -64,6 +68,7 @@ func NewArgoApplicationServiceImpl(logger *zap.SugaredLogger, k8sUtil: k8sUtil, argoUserService: argoUserService, helmAppService: helmAppService, + helmAppClient: helmAppClient, } } @@ -450,3 +455,41 @@ func (impl *ArgoApplicationServiceImpl) GetRestConfigForExternalArgo(ctx context } return restConfig, nil } + +func (impl *ArgoApplicationServiceImpl) HibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + _, clusterBean, _, err := impl.GetClusterConfigFromAllClusters(app.ClusterId) + if err != nil { + impl.logger.Errorw("HibernateArgoApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.AppName) + return nil, err + } + conf := ConvertClusterBeanToGrpcConfig(clusterBean) + + req := service.HibernateReqAdaptor(hibernateRequest) + req.ClusterConfig = conf + res, err := impl.helmAppClient.Hibernate(ctx, req) + if err != nil { + impl.logger.Errorw("HibernateArgoApplication", "error in hibernating the requested resource", err, "clusterId", app.ClusterId, "appName", app.AppName) + return nil, err + } + response := service.HibernateResponseAdaptor(res.Status) + return response, nil +} + +func (impl *ArgoApplicationServiceImpl) UnHibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + _, clusterBean, _, err := impl.GetClusterConfigFromAllClusters(app.ClusterId) + if err != nil { + impl.logger.Errorw("HibernateArgoApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.AppName) + return nil, err + } + conf := ConvertClusterBeanToGrpcConfig(clusterBean) + + req := service.HibernateReqAdaptor(hibernateRequest) + req.ClusterConfig = conf + res, err := impl.helmAppClient.UnHibernate(ctx, req) + if err != nil { + impl.logger.Errorw("UnHibernateArgoApplication", "error in unHibernating the requested resources", err, "clusterId", app.ClusterId, "appName", app.AppName) + return nil, err + } + response := service.HibernateResponseAdaptor(res.Status) + return response, nil +} diff --git a/pkg/argoApplication/bean/bean.go b/pkg/argoApplication/bean/bean.go index 4fb2b1bcbc..899eff0f6c 100644 --- a/pkg/argoApplication/bean/bean.go +++ b/pkg/argoApplication/bean/bean.go @@ -80,3 +80,9 @@ type ArgoClusterConfigObj struct { CaData string `json:"caData,omitempty"` } `json:"tlsClientConfig"` } + +type ArgoAppIdentifier struct { + ClusterId int `json:"clusterId"` + Namespace string `json:"namespace"` + AppName string `json:"appName"` +} diff --git a/pkg/argoApplication/helper.go b/pkg/argoApplication/helper.go new file mode 100644 index 0000000000..97a80e2c4d --- /dev/null +++ b/pkg/argoApplication/helper.go @@ -0,0 +1,47 @@ +package argoApplication + +import ( + "fmt" + "github.com/devtron-labs/common-lib/utils/k8s" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + "github.com/devtron-labs/devtron/pkg/argoApplication/bean" + "github.com/devtron-labs/devtron/pkg/cluster/repository" + "strconv" + "strings" +) + +func DecodeExternalArgoAppId(appId string) (*bean.ArgoAppIdentifier, error) { + component := strings.Split(appId, "|") + if len(component) != 3 { + return nil, fmt.Errorf("malformed app id %s", appId) + } + clusterId, err := strconv.Atoi(component[0]) + if err != nil { + return nil, err + } + if clusterId <= 0 { + return nil, fmt.Errorf("target cluster is not provided") + } + return &bean.ArgoAppIdentifier{ + ClusterId: clusterId, + Namespace: component[1], + AppName: component[2], + }, nil +} + +func ConvertClusterBeanToGrpcConfig(cluster repository.Cluster) *gRPC.ClusterConfig { + config := &gRPC.ClusterConfig{ + ApiServerUrl: cluster.ServerUrl, + Token: cluster.Config[k8s.BearerToken], + ClusterId: int32(cluster.Id), + ClusterName: cluster.ClusterName, + InsecureSkipTLSVerify: cluster.InsecureSkipTlsVerify, + } + if cluster.InsecureSkipTlsVerify == false { + config.KeyData = cluster.Config[k8s.TlsKey] + config.CertData = cluster.Config[k8s.CertData] + config.CaData = cluster.Config[k8s.CertificateAuthorityData] + } + return config + +} diff --git a/pkg/bean/app.go b/pkg/bean/app.go index bb83e5dfe6..bfcc00ce1b 100644 --- a/pkg/bean/app.go +++ b/pkg/bean/app.go @@ -948,3 +948,12 @@ const CustomAutoScalingEnabledPathKey = "CUSTOM_AUTOSCALING_ENABLED_PATH" const CustomAutoscalingReplicaCountPathKey = "CUSTOM_AUTOSCALING_REPLICA_COUNT_PATH" const CustomAutoscalingMinPathKey = "CUSTOM_AUTOSCALING_MIN_PATH" const CustomAutoscalingMaxPathKey = "CUSTOM_AUTOSCALING_MAX_PATH" + +type JsonPath string + +func (j JsonPath) String() string { + return string(j) +} + +const ConfigHashPathKey JsonPath = "devtronInternal.containerSpecs.ConfigHash" +const SecretHashPathKey JsonPath = "devtronInternal.containerSpecs.SecretHash" diff --git a/pkg/deployment/gitOps/config/GitOpsConfigReadService.go b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go index f185033860..d91f014fc9 100644 --- a/pkg/deployment/gitOps/config/GitOpsConfigReadService.go +++ b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go @@ -155,6 +155,7 @@ func (impl *GitOpsConfigReadServiceImpl) GetGitOpsConfigActive() (*bean2.GitOpsC BitBucketWorkspaceId: model.BitBucketWorkspaceId, BitBucketProjectKey: model.BitBucketProjectKey, AllowCustomRepository: model.AllowCustomRepository, + EnableTLSVerification: true, TLSConfig: &bean3.TLSConfig{ CaData: model.CaCert, TLSCertData: model.TlsCert, diff --git a/pkg/deployment/gitOps/git/GitOpsHelper.go b/pkg/deployment/gitOps/git/GitOpsHelper.go index 2d204ef8a0..bc7add2ff9 100644 --- a/pkg/deployment/gitOps/git/GitOpsHelper.go +++ b/pkg/deployment/gitOps/git/GitOpsHelper.go @@ -89,6 +89,7 @@ func (impl *GitOpsHelper) Clone(url, targetDir string) (clonedDir string, err er } } if errMsg != "" { + impl.logger.Errorw("error in git fetch command", "errMsg", errMsg, "err", err) return "", fmt.Errorf(errMsg) } return clonedDir, nil diff --git a/pkg/deployment/gitOps/git/GitServiceAzure.go b/pkg/deployment/gitOps/git/GitServiceAzure.go index e8682cade8..4252901a23 100644 --- a/pkg/deployment/gitOps/git/GitServiceAzure.go +++ b/pkg/deployment/gitOps/git/GitServiceAzure.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" bean2 "github.com/devtron-labs/devtron/api/bean/gitOps" + globalUtil "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/retryFunc" "github.com/microsoft/azure-devops-go-api/azuredevops" "github.com/microsoft/azure-devops-go-api/azuredevops/git" @@ -39,6 +40,12 @@ type GitAzureClient struct { } func (impl GitAzureClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { + + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("GetRepoUrl", "GitAzureClient", start, err) + }() + url, exists, err := impl.repoExists(config.GitRepoName, impl.project) if err != nil { return "", err @@ -67,7 +74,12 @@ func NewGitAzureClient(token string, host string, project string, logger *zap.Su }, err } -func (impl GitAzureClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { +func (impl GitAzureClient) DeleteRepository(config *bean2.GitOpsConfigDto) (err error) { + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CreateRepository", "GitAzureClient", start, err) + }() + clientAzure := *impl.client gitRepository, err := clientAzure.GetRepository(context.Background(), git.GetRepositoryArgs{ RepositoryId: &config.GitRepoName, @@ -85,6 +97,12 @@ func (impl GitAzureClient) DeleteRepository(config *bean2.GitOpsConfigDto) error } func (impl GitAzureClient) CreateRepository(ctx context.Context, config *bean2.GitOpsConfigDto) (url string, isNew bool, detailedErrorGitOpsConfigActions DetailedErrorGitOpsConfigActions) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CreateRepository", "GitAzureClient", start, err) + }() + detailedErrorGitOpsConfigActions.StageErrorMap = make(map[string]error) url, repoExists, err := impl.repoExists(config.GitRepoName, impl.project) if err != nil { @@ -152,6 +170,13 @@ func (impl GitAzureClient) CreateRepository(ctx context.Context, config *bean2.G } func (impl GitAzureClient) CreateReadme(ctx context.Context, config *bean2.GitOpsConfigDto) (string, error) { + + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CreateReadme", "GitAzureClient", start, err) + }() + cfg := &ChartConfig{ ChartName: config.GitRepoName, ChartLocation: "", @@ -272,6 +297,12 @@ func (impl GitAzureClient) CommitValues(ctx context.Context, config *ChartConfig } func (impl GitAzureClient) repoExists(repoName, projectName string) (repoUrl string, exists bool, err error) { + + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("repoExists", "GitAzureClient", start, err) + }() + ctx := context.Background() // Get first page of the list of team projects for your organization clientAzure := *impl.client @@ -295,6 +326,12 @@ func (impl GitAzureClient) repoExists(repoName, projectName string) (repoUrl str } func (impl GitAzureClient) ensureProjectAvailabilityOnHttp(repoName string) (bool, error) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("ensureProjectAvailabilityOnHttp", "GitAzureClient", start, err) + }() + for count := 0; count < 5; count++ { _, exists, err := impl.repoExists(repoName, impl.project) if err == nil && exists { diff --git a/pkg/deployment/gitOps/git/GitServiceBitbucket.go b/pkg/deployment/gitOps/git/GitServiceBitbucket.go index 606da7d434..ab4efa3fb0 100644 --- a/pkg/deployment/gitOps/git/GitServiceBitbucket.go +++ b/pkg/deployment/gitOps/git/GitServiceBitbucket.go @@ -63,21 +63,30 @@ func NewGitBitbucketClient(username, token, host string, logger *zap.SugaredLogg } } -func (impl GitBitbucketClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { +func (impl GitBitbucketClient) DeleteRepository(config *bean2.GitOpsConfigDto) (err error) { + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("DeleteRepository", "GitBitbucketClient", start, err) + }() repoOptions := &bitbucket.RepositoryOptions{ Owner: config.BitBucketWorkspaceId, RepoSlug: config.GitRepoName, IsPrivate: "true", Project: config.BitBucketProjectKey, } - _, err := impl.client.Repositories.Repository.Delete(repoOptions) + _, err = impl.client.Repositories.Repository.Delete(repoOptions) if err != nil { - impl.logger.Errorw("error in deleting repo gitlab", "repoName", repoOptions.RepoSlug, "err", err) + impl.logger.Errorw("error in deleting repo gitlab", "repoName", config.GitRepoName, "err", err) } return err } func (impl GitBitbucketClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("GetRepoUrl", "GitBitbucketClient", start, err) + }() + repoOptions := &bitbucket.RepositoryOptions{ Owner: config.BitBucketWorkspaceId, Project: config.BitBucketProjectKey, @@ -95,6 +104,12 @@ func (impl GitBitbucketClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUr } func (impl GitBitbucketClient) CreateRepository(ctx context.Context, config *bean2.GitOpsConfigDto) (url string, isNew bool, detailedErrorGitOpsConfigActions DetailedErrorGitOpsConfigActions) { + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CreateRepository", "GitBitbucketClient", start, err) + }() + detailedErrorGitOpsConfigActions.StageErrorMap = make(map[string]error) workSpaceId := config.BitBucketWorkspaceId @@ -107,6 +122,7 @@ func (impl GitBitbucketClient) CreateRepository(ctx context.Context, config *bea Description: config.Description, Project: projectKey, } + repoUrl, repoExists, err := impl.repoExists(repoOptions) if err != nil { impl.logger.Errorw("error in communication with bitbucket", "repoOptions", repoOptions, "err", err) @@ -168,6 +184,12 @@ func (impl GitBitbucketClient) CreateRepository(ctx context.Context, config *bea } func (impl GitBitbucketClient) repoExists(repoOptions *bitbucket.RepositoryOptions) (repoUrl string, exists bool, err error) { + + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("repoExists", "GitBitbucketClient", start, err) + }() + repo, err := impl.client.Repositories.Repository.Get(repoOptions) if repo == nil && err.Error() == BITBUCKET_REPO_NOT_FOUND_ERROR { return "", false, nil @@ -202,6 +224,12 @@ func getDir() string { } func (impl GitBitbucketClient) CreateReadme(ctx context.Context, config *bean2.GitOpsConfigDto) (string, error) { + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CreateReadme", "GitBitbucketClient", start, err) + }() + cfg := &ChartConfig{ ChartName: config.GitRepoName, ChartLocation: "", @@ -242,6 +270,12 @@ func (impl GitBitbucketClient) cleanUp(cloneDir string) { } func (impl GitBitbucketClient) CommitValues(ctx context.Context, config *ChartConfig, gitOpsConfig *bean2.GitOpsConfigDto) (commitHash string, commitTime time.Time, err error) { + + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CommitValues", "GitBitbucketClient", start, err) + }() + homeDir, err := os.UserHomeDir() if err != nil { impl.logger.Errorw("error in getting home dir", "err", err) diff --git a/pkg/deployment/gitOps/git/GitServiceGithub.go b/pkg/deployment/gitOps/git/GitServiceGithub.go index 0ec43594c8..b48d8b5ab4 100644 --- a/pkg/deployment/gitOps/git/GitServiceGithub.go +++ b/pkg/deployment/gitOps/git/GitServiceGithub.go @@ -21,6 +21,7 @@ import ( "crypto/tls" "fmt" bean2 "github.com/devtron-labs/devtron/api/bean/gitOps" + globalUtil "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/retryFunc" "github.com/google/go-github/github" "go.uber.org/zap" @@ -76,7 +77,13 @@ func NewGithubClient(host string, token string, org string, logger *zap.SugaredL } func (impl GitHubClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { - _, err := impl.client.Repositories.Delete(context.Background(), config.GitHubOrgId, config.GitRepoName) + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("DeleteRepository", "GitHubClient", start, err) + }() + + _, err = impl.client.Repositories.Delete(context.Background(), config.GitHubOrgId, config.GitRepoName) if err != nil { impl.logger.Errorw("repo deletion failed for github", "repo", config.GitRepoName, "err", err) return err @@ -85,9 +92,15 @@ func (impl GitHubClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { } func (impl GitHubClient) CreateRepository(ctx context.Context, config *bean2.GitOpsConfigDto) (url string, isNew bool, detailedErrorGitOpsConfigActions DetailedErrorGitOpsConfigActions) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CreateRepository", "GitHubClient", start, err) + }() + detailedErrorGitOpsConfigActions.StageErrorMap = make(map[string]error) repoExists := true - url, err := impl.GetRepoUrl(config) + url, err = impl.GetRepoUrl(config) if err != nil { responseErr, ok := err.(*github.ErrorResponse) if !ok || responseErr.Response.StatusCode != 404 { @@ -158,6 +171,12 @@ func (impl GitHubClient) CreateRepository(ctx context.Context, config *bean2.Git } func (impl GitHubClient) CreateReadme(ctx context.Context, config *bean2.GitOpsConfigDto) (string, error) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CreateReadme", "GitHubClient", start, err) + }() + cfg := &ChartConfig{ ChartName: config.GitRepoName, ChartLocation: "", @@ -176,6 +195,12 @@ func (impl GitHubClient) CreateReadme(ctx context.Context, config *bean2.GitOpsC } func (impl GitHubClient) CommitValues(ctx context.Context, config *ChartConfig, gitOpsConfig *bean2.GitOpsConfigDto) (commitHash string, commitTime time.Time, err error) { + + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("CommitValues", "GitHubClient", start, err) + }() + branch := "master" path := filepath.Join(config.ChartLocation, config.FileName) newFile := false @@ -226,15 +251,27 @@ func (impl GitHubClient) CommitValues(ctx context.Context, config *ChartConfig, } func (impl GitHubClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("GetRepoUrl", "GitHubClient", start, err) + }() + ctx := context.Background() repo, _, err := impl.client.Repositories.Get(ctx, impl.org, config.GitRepoName) if err != nil { + impl.logger.Errorw("error in getting repo url by repo name", "org", impl.org, "gitRepoName", config.GitRepoName, "err", err) return "", err } return *repo.CloneURL, nil } func (impl GitHubClient) ensureProjectAvailabilityOnHttp(config *bean2.GitOpsConfigDto) (bool, error) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("ensureProjectAvailabilityOnHttp", "GitHubClient", start, err) + }() + count := 0 for count < 3 { count = count + 1 @@ -255,6 +292,12 @@ func (impl GitHubClient) ensureProjectAvailabilityOnHttp(config *bean2.GitOpsCon } func (impl GitHubClient) ensureProjectAvailabilityOnSsh(projectName string, repoUrl string) (bool, error) { + var err error + start := time.Now() + defer func() { + globalUtil.TriggerGitOpsMetrics("ensureProjectAvailabilityOnSsh", "GitHubClient", start, err) + }() + count := 0 for count < 3 { count = count + 1 diff --git a/pkg/deployment/gitOps/git/GitServiceGitlab.go b/pkg/deployment/gitOps/git/GitServiceGitlab.go index b4a91de319..5182d65bb3 100644 --- a/pkg/deployment/gitOps/git/GitServiceGitlab.go +++ b/pkg/deployment/gitOps/git/GitServiceGitlab.go @@ -114,8 +114,13 @@ func CreateGitlabClient(host, token string, tlsConfig *tls.Config) (*gitlab.Clie return gitLabClient, err } -func (impl GitLabClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { - err := impl.DeleteProject(config.GitRepoName) +func (impl GitLabClient) DeleteRepository(config *bean2.GitOpsConfigDto) (err error) { + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("DeleteRepository", "GitLabClient", start, err) + }() + + err = impl.DeleteProject(config.GitRepoName) if err != nil { impl.logger.Errorw("error in deleting repo gitlab", "project", config.GitRepoName, "err", err) } @@ -123,6 +128,13 @@ func (impl GitLabClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { } func (impl GitLabClient) CreateRepository(ctx context.Context, config *bean2.GitOpsConfigDto) (url string, isNew bool, detailedErrorGitOpsConfigActions DetailedErrorGitOpsConfigActions) { + + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CreateRepository", "GitLabClient", start, err) + }() + detailedErrorGitOpsConfigActions.StageErrorMap = make(map[string]error) impl.logger.Debugw("gitlab app create request ", "name", config.GitRepoName, "description", config.Description) repoUrl, err := impl.GetRepoUrl(config) @@ -182,11 +194,21 @@ func (impl GitLabClient) CreateRepository(ctx context.Context, config *bean2.Git } func (impl GitLabClient) DeleteProject(projectName string) (err error) { + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("DeleteProject", "GitLabClient", start, err) + }() + impl.logger.Infow("deleting project ", "gitlab project name", projectName) _, err = impl.client.Projects.DeleteProject(fmt.Sprintf("%s/%s", impl.config.GitlabGroupPath, projectName)) return err } func (impl GitLabClient) createProject(name, description string) (url string, err error) { + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("createProject", "GitLabClient", start, err) + }() + var namespace = impl.config.GitlabGroupId namespaceId, err := strconv.Atoi(namespace) if err != nil { @@ -212,6 +234,13 @@ func (impl GitLabClient) createProject(name, description string) (url string, er } func (impl GitLabClient) ensureProjectAvailability(projectName string) (bool, error) { + + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("ensureProjectAvailability", "GitLabClient", start, err) + }() + pid := fmt.Sprintf("%s/%s", impl.config.GitlabGroupPath, projectName) count := 0 verified := false @@ -231,6 +260,12 @@ func (impl GitLabClient) ensureProjectAvailability(projectName string) (bool, er } func (impl GitLabClient) ensureProjectAvailabilityOnSsh(projectName string, repoUrl string) (bool, error) { + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("ensureProjectAvailabilityOnSsh", "GitLabClient", start, err) + }() + count := 0 for count < 3 { count = count + 1 @@ -248,6 +283,12 @@ func (impl GitLabClient) ensureProjectAvailabilityOnSsh(projectName string, repo } func (impl GitLabClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { + + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("GetRepoUrl", "GitLabClient", start, err) + }() + pid := fmt.Sprintf("%s/%s", impl.config.GitlabGroupPath, config.GitRepoName) prop, res, err := impl.client.Projects.GetProject(pid, &gitlab.GetProjectOptions{}) if err != nil { @@ -264,6 +305,12 @@ func (impl GitLabClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl stri } func (impl GitLabClient) CreateReadme(ctx context.Context, config *bean2.GitOpsConfigDto) (string, error) { + var err error + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CreateReadme", "GitLabClient", start, err) + }() + fileAction := gitlab.FileCreate filePath := "README.md" fileContent := "devtron licence" @@ -293,6 +340,12 @@ func (impl GitLabClient) checkIfFileExists(projectName, ref, file string) (exist } func (impl GitLabClient) CommitValues(ctx context.Context, config *ChartConfig, gitOpsConfig *bean2.GitOpsConfigDto) (commitHash string, commitTime time.Time, err error) { + + start := time.Now() + defer func() { + util.TriggerGitOpsMetrics("CommitValues", "GitLabClient", start, err) + }() + branch := "master" path := filepath.Join(config.ChartLocation, config.FileName) exists, err := impl.checkIfFileExists(config.ChartRepoName, branch, path) diff --git a/pkg/deployment/gitOps/git/commandManager/GitCliManager.go b/pkg/deployment/gitOps/git/commandManager/GitCliManager.go index 5640fba0a0..b5b3a3a146 100644 --- a/pkg/deployment/gitOps/git/commandManager/GitCliManager.go +++ b/pkg/deployment/gitOps/git/commandManager/GitCliManager.go @@ -77,6 +77,9 @@ func (impl *GitCliManagerImpl) Pull(ctx GitContext, repoRoot string) (err error) return err } response, errMsg, err := impl.PullCli(ctx, repoRoot, "origin/master") + if err != nil { + impl.logger.Errorw("error in git pull from cli", "errMsg", errMsg, "err", err) + } if strings.Contains(response, "already up-to-date") || strings.Contains(errMsg, "already up-to-date") { err = nil @@ -89,7 +92,7 @@ func (impl *GitCliManagerImpl) gitInit(ctx GitContext, rootDir string) error { impl.logger.Debugw("git inti", "rootDir", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "init") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -113,7 +116,7 @@ func (impl *GitCliManagerImpl) commit(ctx GitContext, rootDir string, commitMsg author := fmt.Sprintf("%s <%s>", user, email) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "commit", "--allow-empty", "-m", commitMsg, "--author", author) defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -128,7 +131,7 @@ func (impl *GitCliManagerImpl) lastCommitHash(ctx GitContext, rootDir string) (r impl.logger.Debugw("git log", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "log", "--format=format:%H", "-n", "1") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -143,7 +146,7 @@ func (impl *GitCliManagerImpl) add(ctx GitContext, rootDir string) (response, er impl.logger.Debugw("git add", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "add", "-A") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -158,7 +161,7 @@ func (impl *GitCliManagerImpl) push(ctx GitContext, rootDir string) (response, e impl.logger.Debugw("git push", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "push", "origin", "master") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -173,7 +176,7 @@ func (impl *GitCliManagerImpl) gitCreateRemote(ctx GitContext, rootDir string, u impl.logger.Debugw("git remote", "rootDir", rootDir, "url", url) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "remote", "add", "origin", url) defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) diff --git a/pkg/deployment/gitOps/git/commandManager/GitCommandBaseManager.go b/pkg/deployment/gitOps/git/commandManager/GitCommandBaseManager.go index efe4ad82e0..f10894d1d1 100644 --- a/pkg/deployment/gitOps/git/commandManager/GitCommandBaseManager.go +++ b/pkg/deployment/gitOps/git/commandManager/GitCommandBaseManager.go @@ -47,7 +47,7 @@ func (impl *GitManagerBaseImpl) Fetch(ctx GitContext, rootDir string) (response, impl.logger.Debugw("git fetch ", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "fetch", "origin", "--tags", "--force") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -66,7 +66,7 @@ func (impl *GitManagerBaseImpl) ListBranch(ctx GitContext, rootDir string) (resp impl.logger.Debugw("git branch ", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "branch", "-r") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) @@ -85,7 +85,7 @@ func (impl *GitManagerBaseImpl) PullCli(ctx GitContext, rootDir string, branch s impl.logger.Debugw("git pull ", "location", rootDir) cmd, cancel := impl.createCmdWithContext(ctx, "git", "-C", rootDir, "pull", "origin", branch, "--force") defer cancel() - tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), git_manager.TLS_FILES_DIR) + tlsPathInfo, err := git_manager.CreateFilesForTlsData(git_manager.BuildTlsData(ctx.TLSKey, ctx.TLSCertificate, ctx.CACert, ctx.TLSVerificationEnabled), TLS_FOLDER) if err != nil { //making it non-blocking impl.logger.Errorw("error encountered in createFilesForTlsData", "err", err) diff --git a/pkg/deployment/gitOps/git/commandManager/GoGitSdkManager.go b/pkg/deployment/gitOps/git/commandManager/GoGitSdkManager.go index 950a0bf451..3d70a73c31 100644 --- a/pkg/deployment/gitOps/git/commandManager/GoGitSdkManager.go +++ b/pkg/deployment/gitOps/git/commandManager/GoGitSdkManager.go @@ -56,6 +56,9 @@ func (impl GoGitSDKManagerImpl) Pull(ctx GitContext, repoRoot string) (err error } err = workTree.PullContext(ctx, pullOptions) + if err != nil { + impl.logger.Errorw("error in git pull from go-git", "err", err) + } if err != nil && err.Error() == "already up-to-date" { err = nil return nil diff --git a/pkg/deployment/manifest/ManifestCreationService.go b/pkg/deployment/manifest/ManifestCreationService.go index 85b1ccd8ff..9b2cc19927 100644 --- a/pkg/deployment/manifest/ManifestCreationService.go +++ b/pkg/deployment/manifest/ManifestCreationService.go @@ -18,6 +18,7 @@ package manifest import ( "context" + "crypto/sha256" "encoding/json" "fmt" application3 "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" @@ -30,7 +31,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/app" - bean2 "github.com/devtron-labs/devtron/pkg/bean" + appBean "github.com/devtron-labs/devtron/pkg/bean" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/deployment/common" @@ -47,12 +48,14 @@ import ( "github.com/devtron-labs/devtron/pkg/variables" "github.com/devtron-labs/devtron/pkg/variables/parsers" repository5 "github.com/devtron-labs/devtron/pkg/variables/repository" - util4 "github.com/devtron-labs/devtron/util" + globalUtil "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg" errors2 "github.com/juju/errors" "github.com/tidwall/gjson" + "github.com/tidwall/sjson" "go.opentelemetry.io/otel" "go.uber.org/zap" + k8sApiV1 "k8s.io/api/core/v1" "net/http" "strings" "time" @@ -190,9 +193,10 @@ func (impl *ManifestCreationServiceImpl) GetValuesOverrideForTrigger(overrideReq } var ( - pipelineOverride *chartConfig.PipelineOverride - configMapJson, appLabelJsonByte []byte - envOverride *chartConfig.EnvConfigOverride + pipelineOverride *chartConfig.PipelineOverride + appLabelJsonByte []byte + configMapJson *bean3.MergedCmAndCsJsonV2Response + envOverride *chartConfig.EnvConfigOverride ) if isPipelineOverrideCreated { pipelineOverride, err = impl.pipelineOverrideRepository.FindById(overrideRequest.PipelineOverrideId) @@ -248,7 +252,7 @@ func (impl *ManifestCreationServiceImpl) GetValuesOverrideForTrigger(overrideReq if !isPipelineOverrideCreated { chartVersion := envOverride.Chart.ChartVersion scope := helper.GetScopeForVariables(overrideRequest, envOverride) - request := helper.CreateConfigMapAndSecretJsonRequest(overrideRequest, envOverride, chartVersion, scope) + request := helper.NewMergedCmAndCsJsonV2Request(overrideRequest, envOverride, chartVersion, scope) configMapJson, err = impl.getConfigMapAndSecretJsonV2(newCtx, request, envOverride) if err != nil { @@ -260,14 +264,24 @@ func (impl *ManifestCreationServiceImpl) GetValuesOverrideForTrigger(overrideReq impl.logger.Errorw("error in fetching app labels for gitOps commit", "err", err) appLabelJsonByte = nil } - mergedValues, err := impl.mergeOverrideValues(envOverride, releaseOverrideJson, configMapJson, appLabelJsonByte, strategy) + mergedValues, err := impl.mergeOverrideValues(envOverride, releaseOverrideJson, configMapJson.MergedJson, appLabelJsonByte, strategy) appName := fmt.Sprintf("%s-%s", overrideRequest.AppName, envOverride.Environment.Name) - mergedValues, err = impl.autoscalingCheckBeforeTrigger(newCtx, appName, envOverride.Namespace, mergedValues, overrideRequest) - if err != nil { - impl.logger.Errorw("error in autoscaling check before trigger", "pipelineId", overrideRequest.PipelineId, "err", err) - return valuesOverrideResponse, err + var k8sErr error + mergedValues, k8sErr = impl.updatedExternalCmCsHashForTrigger(newCtx, overrideRequest.ClusterId, + envOverride.Namespace, mergedValues, configMapJson.ExternalCmList, configMapJson.ExternalCsList) + if k8sErr != nil { + impl.logger.Errorw("error in updating external cm cs hash for trigger", + "clusterId", overrideRequest.ClusterId, "namespace", envOverride.Namespace, "err", k8sErr) + // error is not returned as it's not blocking for deployment process + // blocking deployments based on this use case can vary for user to user + } + if !envOverride.Environment.IsVirtualEnvironment { + mergedValues, err = impl.autoscalingCheckBeforeTrigger(newCtx, appName, envOverride.Namespace, mergedValues, overrideRequest) + if err != nil { + impl.logger.Errorw("error in autoscaling check before trigger", "pipelineId", overrideRequest.PipelineId, "err", err) + return valuesOverrideResponse, err + } } - // handle image pull secret if access given mergedValues, err = impl.dockerRegistryIpsConfigService.HandleImagePullSecretOnApplicationDeployment(newCtx, envOverride.Environment, artifact, pipeline.CiPipelineId, mergedValues) if err != nil { @@ -560,7 +574,7 @@ func (impl *ManifestCreationServiceImpl) mergeOverrideValues(envOverride *chartC return merged, nil } -func (impl *ManifestCreationServiceImpl) getConfigMapAndSecretJsonV2(ctx context.Context, request bean3.ConfigMapAndSecretJsonV2, envOverride *chartConfig.EnvConfigOverride) ([]byte, error) { +func (impl *ManifestCreationServiceImpl) getConfigMapAndSecretJsonV2(ctx context.Context, request bean3.GetMergedCmAndCsJsonV2Request, envOverride *chartConfig.EnvConfigOverride) (*bean3.MergedCmAndCsJsonV2Response, error) { _, span := otel.Tracer("orchestrator").Start(ctx, "ManifestCreationServiceImpl.getConfigMapAndSecretJsonV2") defer span.End() var configMapJson, secretDataJson, configMapJsonApp, secretDataJsonApp, configMapJsonEnv, secretDataJsonEnv string @@ -570,11 +584,11 @@ func (impl *ManifestCreationServiceImpl) getConfigMapAndSecretJsonV2(ctx context configMapE := &chartConfig.ConfigMapEnvModel{} configMapHistory, secretHistory := &repository3.ConfigmapAndSecretHistory{}, &repository3.ConfigmapAndSecretHistory{} - merged := []byte("{}") + cmAndCsJsonV2Response := helper.NewMergedCmAndCsJsonV2Response() if request.DeploymentWithConfig == bean.DEPLOYMENT_CONFIG_TYPE_LAST_SAVED { configMapA, err = impl.configMapRepository.GetByAppIdAppLevel(request.AppId) if err != nil && pg.ErrNoRows != err { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } if configMapA != nil && configMapA.Id > 0 { configMapJsonApp = configMapA.ConfigMapData @@ -583,7 +597,7 @@ func (impl *ManifestCreationServiceImpl) getConfigMapAndSecretJsonV2(ctx context configMapE, err = impl.configMapRepository.GetByAppIdAndEnvIdEnvLevel(request.AppId, request.EnvId) if err != nil && pg.ErrNoRows != err { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } if configMapE != nil && configMapE.Id > 0 { configMapJsonEnv = configMapE.ConfigMapData @@ -592,76 +606,98 @@ func (impl *ManifestCreationServiceImpl) getConfigMapAndSecretJsonV2(ctx context } else if request.DeploymentWithConfig == bean.DEPLOYMENT_CONFIG_TYPE_SPECIFIC_TRIGGER { - //fetching history and setting envLevelConfig and not appLevelConfig because history already contains merged appLevel and envLevel configs + // fetching history and setting envLevelConfig and not appLevelConfig because history already contains merged appLevel and envLevel configs configMapHistory, err = impl.configMapHistoryRepository.GetHistoryByPipelineIdAndWfrId(request.PipeLineId, request.WfrIdForDeploymentWithSpecificTrigger, repository3.CONFIGMAP_TYPE) if err != nil { impl.logger.Errorw("error in getting config map history config by pipelineId and wfrId ", "err", err, "pipelineId", request.PipeLineId, "wfrId", request.WfrIdForDeploymentWithSpecificTrigger) - return []byte("{}"), err + return cmAndCsJsonV2Response, err } configMapJsonEnv = configMapHistory.Data secretHistory, err = impl.configMapHistoryRepository.GetHistoryByPipelineIdAndWfrId(request.PipeLineId, request.WfrIdForDeploymentWithSpecificTrigger, repository3.SECRET_TYPE) if err != nil { impl.logger.Errorw("error in getting config map history config by pipelineId and wfrId ", "err", err, "pipelineId", request.PipeLineId, "wfrId", request.WfrIdForDeploymentWithSpecificTrigger) - return []byte("{}"), err + return cmAndCsJsonV2Response, err } secretDataJsonEnv = secretHistory.Data } configMapJson, err = impl.mergeUtil.ConfigMapMerge(configMapJsonApp, configMapJsonEnv) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } - chartMajorVersion, chartMinorVersion, err := util4.ExtractChartVersion(request.ChartVersion) + chartMajorVersion, chartMinorVersion, err := globalUtil.ExtractChartVersion(request.ChartVersion) if err != nil { impl.logger.Errorw("chart version parsing", "err", err) - return []byte("{}"), err + return cmAndCsJsonV2Response, err } secretDataJson, err = impl.mergeUtil.ConfigSecretMerge(secretDataJsonApp, secretDataJsonEnv, chartMajorVersion, chartMinorVersion, false) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } - configResponseR := bean.ConfigMapRootJson{} + cmRootJson := bean.ConfigMapRootJson{} configResponse := bean.ConfigMapJson{} if configMapJson != "" { err = json.Unmarshal([]byte(configMapJson), &configResponse) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } } - configResponseR.ConfigMapJson = configResponse - secretResponseR := bean.ConfigSecretRootJson{} + cmRootJson.ConfigMapJson = configResponse + csRootJson := bean.ConfigSecretRootJson{} secretResponse := bean.ConfigSecretJson{} if configMapJson != "" { err = json.Unmarshal([]byte(secretDataJson), &secretResponse) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } } - secretResponseR.ConfigSecretJson = secretResponse + csRootJson.ConfigSecretJson = secretResponse - configMapByte, err := json.Marshal(configResponseR) + configMapByte, err := json.Marshal(cmRootJson) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } - secretDataByte, err := json.Marshal(secretResponseR) + secretDataByte, err := json.Marshal(csRootJson) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } resolvedCM, resolvedCS, snapshotCM, snapshotCS, err := impl.scopedVariableManager.ResolveCMCSTrigger(request.DeploymentWithConfig, request.Scope, configMapA.Id, configMapE.Id, configMapByte, secretDataByte, configMapHistory.Id, secretHistory.Id) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } envOverride.VariableSnapshotForCM = snapshotCM envOverride.VariableSnapshotForCS = snapshotCS - merged, err = impl.mergeUtil.JsonPatch([]byte(resolvedCM), []byte(resolvedCS)) - + cmAndCsJsonV2Response.MergedJson, err = impl.mergeUtil.JsonPatch([]byte(resolvedCM), []byte(resolvedCS)) if err != nil { - return []byte("{}"), err + return cmAndCsJsonV2Response, err } + cmAndCsJsonV2Response.ExternalCmList, cmAndCsJsonV2Response.ExternalCsList = getExternalCmCsFromRootJson(cmRootJson, csRootJson) + return cmAndCsJsonV2Response, nil +} - return merged, nil +// getExternalCmCsFromRootJson returns the list of external configmaps and secrets from the root json +func getExternalCmCsFromRootJson(cmRootJson bean.ConfigMapRootJson, csRootJson bean.ConfigSecretRootJson) (externalCsList []string, externalCmList []string) { + externalCmList = make([]string, 0) + externalCsList = make([]string, 0) + if cmRootJson.ConfigMapJson.Enabled { + for _, cm := range cmRootJson.ConfigMapJson.Maps { + if cm.External { + externalCmList = append(externalCmList, cm.Name) + } + } + } + if csRootJson.ConfigSecretJson.Enabled { + for _, cs := range csRootJson.ConfigSecretJson.Secrets { + // Only handling for KubernetesSecret type + // KubernetesExternalSecret types are excluded for Config/Secret Hashing + if cs.External && cs.ExternalType == globalUtil.KubernetesSecret { + externalCsList = append(externalCsList, cs.Name) + } + } + } + return externalCmList, externalCsList } func (impl *ManifestCreationServiceImpl) getReleaseOverride(envOverride *chartConfig.EnvConfigOverride, overrideRequest *bean.ValuesOverrideRequest, @@ -772,7 +808,7 @@ func (impl *ManifestCreationServiceImpl) checkAndFixDuplicateReleaseNo(override return err } override.PipelineReleaseCounter = currentReleaseNo + 1 - err = impl.pipelineOverrideRepository.Save(override) + err = impl.pipelineOverrideRepository.Update(override) if err != nil { return err } @@ -784,7 +820,7 @@ func (impl *ManifestCreationServiceImpl) checkAndFixDuplicateReleaseNo(override return nil } -func (impl *ManifestCreationServiceImpl) getK8sHPAResourceManifest(ctx context.Context, clusterId int, namespace string, hpaResourceRequest *util4.HpaResourceRequest) (map[string]interface{}, error) { +func (impl *ManifestCreationServiceImpl) getK8sHPAResourceManifest(ctx context.Context, clusterId int, namespace string, hpaResourceRequest *globalUtil.HpaResourceRequest) (map[string]interface{}, error) { newCtx, span := otel.Tracer("orchestrator").Start(ctx, "ManifestCreationServiceImpl.getK8sHPAResourceManifest") defer span.End() resourceManifest := make(map[string]interface{}) @@ -837,7 +873,7 @@ func (impl *ManifestCreationServiceImpl) getK8sHPAResourceManifest(ctx context.C return k8sResource.ManifestResponse.Manifest.Object, err } -func (impl *ManifestCreationServiceImpl) getArgoCdHPAResourceManifest(ctx context.Context, appName, namespace string, hpaResourceRequest *util4.HpaResourceRequest) (map[string]interface{}, error) { +func (impl *ManifestCreationServiceImpl) getArgoCdHPAResourceManifest(ctx context.Context, appName, namespace string, hpaResourceRequest *globalUtil.HpaResourceRequest) (map[string]interface{}, error) { newCtx, span := otel.Tracer("orchestrator").Start(ctx, "ManifestCreationServiceImpl.getArgoCdHPAResourceManifest") defer span.End() resourceManifest := make(map[string]interface{}) @@ -853,7 +889,7 @@ func (impl *ManifestCreationServiceImpl) getArgoCdHPAResourceManifest(ctx contex recv, argoErr := impl.acdClient.GetResource(newCtx, query) if argoErr != nil { grpcCode, errMsg := util.GetClientDetailedError(argoErr) - if grpcCode.IsInvalidArgumentCode() { + if grpcCode.IsInvalidArgumentCode() || grpcCode.IsNotFoundCode() { // this is a valid case for hibernated applications, so returning nil // for hibernated applications, we don't have any hpa resource manifest return resourceManifest, nil @@ -882,6 +918,95 @@ func (impl *ManifestCreationServiceImpl) getArgoCdHPAResourceManifest(ctx contex return resourceManifest, nil } +// updateHashToMergedValues +// - Generates hash from the given configOrSecretData +// - And updates the hash in bean.JsonPath (JSON path) for the merged values +// - Returns the updated merged values +func updateHashToMergedValues(merged []byte, path appBean.JsonPath, configOrSecretData map[string]interface{}) ([]byte, error) { + mergedByteData, err := json.Marshal(configOrSecretData) + if err != nil { + return merged, err + } + hash := fmt.Sprintf("%x", sha256.Sum256(mergedByteData)) + mergedString, err := sjson.Set(string(merged), path.String(), hash) + if err != nil { + return merged, err + } + return []byte(mergedString), nil +} + +// getConfigMapsData returns the data of the given configmaps +func getConfigMapsData(configMaps map[string]*k8sApiV1.ConfigMap) map[string]interface{} { + configMapData := make(map[string]interface{}) + for configMapName, configMap := range configMaps { + configMapData[configMapName] = struct { + Data map[string]string `json:"data,omitempty"` + BinaryData map[string][]byte `json:"binaryData,omitempty"` + }{ + Data: configMap.Data, + BinaryData: configMap.BinaryData, + } + } + return configMapData +} + +// getSecretsData returns the data of the given secrets +func getSecretsData(secrets map[string]*k8sApiV1.Secret) map[string]interface{} { + secretData := make(map[string]interface{}) + for secretName, secret := range secrets { + secretData[secretName] = struct { + Data map[string][]byte `json:"data,omitempty"` + StringData map[string]string `json:"stringData,omitempty"` + }{ + Data: secret.Data, + StringData: secret.StringData, + } + } + return secretData +} + +// updatedExternalCmCsHashForTrigger +// - Fetches all the external configmaps and secrets from the given externalCmList and externalCsList +// - Generates hash from the fetched configmaps and secrets and updates the hash in the merged values +// - Returns - the updated merged values +func (impl *ManifestCreationServiceImpl) updatedExternalCmCsHashForTrigger(ctx context.Context, clusterId int, namespace string, merged []byte, externalCmList, externalCsList []string) ([]byte, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "ManifestCreationServiceImpl.updatedExternalCmCsHashForTrigger") + defer span.End() + if len(externalCmList) > 0 { + request := k8s.NewCmCsRequestBean(clusterId, namespace). + SetExternalCmList(externalCmList...) + configMaps, err := impl.k8sCommonService.GetDataFromConfigMaps(newCtx, request) + if err != nil { + impl.logger.Errorw("error in fetching all configmaps", "request", request, "err", err) + return merged, k8s.ParseK8sClientErrorToApiError(err) + } + if configMaps != nil { + merged, err = updateHashToMergedValues(merged, appBean.ConfigHashPathKey, getConfigMapsData(configMaps)) + if err != nil { + impl.logger.Errorw("error in updating hash for configmaps", "err", err) + return merged, err + } + } + } + if len(externalCsList) > 0 { + request := k8s.NewCmCsRequestBean(clusterId, namespace). + SetExternalCsList(externalCsList...) + secrets, err := impl.k8sCommonService.GetDataFromSecrets(newCtx, request) + if err != nil { + impl.logger.Errorw("error in fetching all configmaps", "request", request, "err", err) + return merged, k8s.ParseK8sClientErrorToApiError(err) + } + if secrets != nil { + merged, err = updateHashToMergedValues(merged, appBean.SecretHashPathKey, getSecretsData(secrets)) + if err != nil { + impl.logger.Errorw("error in updating hash for secrets", "err", err) + return merged, err + } + } + } + return merged, nil +} + func (impl *ManifestCreationServiceImpl) autoscalingCheckBeforeTrigger(ctx context.Context, appName string, namespace string, merged []byte, overrideRequest *bean.ValuesOverrideRequest) ([]byte, error) { newCtx, span := otel.Tracer("orchestrator").Start(ctx, "ManifestCreationServiceImpl.autoscalingCheckBeforeTrigger") defer span.End() @@ -914,7 +1039,12 @@ func (impl *ManifestCreationServiceImpl) autoscalingCheckBeforeTrigger(ctx conte if len(resourceManifest) > 0 { statusMap := resourceManifest["status"].(map[string]interface{}) currentReplicaVal := statusMap["currentReplicas"] - currentReplicaCount, err := util4.ParseFloatNumber(currentReplicaVal) + // currentReplicas key might not be available in manifest while k8s is calculating replica count + // it's a valid case so, we are not throwing error + if currentReplicaVal == nil { + return merged, err + } + currentReplicaCount, err := globalUtil.ParseFloatNumber(currentReplicaVal) if err != nil { impl.logger.Errorw("error occurred while parsing replica count", "currentReplicas", currentReplicaVal, "err", err) return merged, err @@ -933,26 +1063,26 @@ func (impl *ManifestCreationServiceImpl) autoscalingCheckBeforeTrigger(ctx conte } //check for custom chart support - if autoscalingEnabledPath, ok := templateMap[bean2.CustomAutoScalingEnabledPathKey]; ok { + if autoscalingEnabledPath, ok := templateMap[appBean.CustomAutoScalingEnabledPathKey]; ok { if deploymentType == models.DEPLOYMENTTYPE_STOP { - merged, err = helper.SetScalingValues(templateMap, bean2.CustomAutoScalingEnabledPathKey, merged, false) + merged, err = helper.SetScalingValues(templateMap, appBean.CustomAutoScalingEnabledPathKey, merged, false) if err != nil { impl.logger.Errorw("error occurred while setting autoscaling enabled key", "templateMap", templateMap, "err", err) return merged, err } - merged, err = helper.SetScalingValues(templateMap, bean2.CustomAutoscalingReplicaCountPathKey, merged, 0) + merged, err = helper.SetScalingValues(templateMap, appBean.CustomAutoscalingReplicaCountPathKey, merged, 0) if err != nil { impl.logger.Errorw("error occurred while setting autoscaling replica count key", "templateMap", templateMap, "err", err) return merged, err } - merged, err = helper.SetScalingValues(templateMap, bean2.CustomAutoscalingMinPathKey, merged, 0) + merged, err = helper.SetScalingValues(templateMap, appBean.CustomAutoscalingMinPathKey, merged, 0) if err != nil { impl.logger.Errorw("error occurred while setting autoscaling min key", "templateMap", templateMap, "err", err) return merged, err } - merged, err = helper.SetScalingValues(templateMap, bean2.CustomAutoscalingMaxPathKey, merged, 0) + merged, err = helper.SetScalingValues(templateMap, appBean.CustomAutoscalingMaxPathKey, merged, 0) if err != nil { impl.logger.Errorw("error occurred while setting autoscaling max key", "templateMap", templateMap, "err", err) return merged, err @@ -969,7 +1099,7 @@ func (impl *ManifestCreationServiceImpl) autoscalingCheckBeforeTrigger(ctx conte if err != nil { return merged, err } - merged, err = helper.SetScalingValues(templateMap, bean2.CustomAutoscalingReplicaCountPathKey, merged, replicaCount) + merged, err = helper.SetScalingValues(templateMap, appBean.CustomAutoscalingReplicaCountPathKey, merged, replicaCount) if err != nil { impl.logger.Errorw("error occurred while setting autoscaling key", "templateMap", templateMap, "err", err) return merged, err @@ -982,34 +1112,34 @@ func (impl *ManifestCreationServiceImpl) autoscalingCheckBeforeTrigger(ctx conte } func (impl *ManifestCreationServiceImpl) getReplicaCountFromCustomChart(templateMap map[string]interface{}, merged []byte) (float64, error) { - autoscalingMinVal, err := helper.ExtractParamValue(templateMap, bean2.CustomAutoscalingMinPathKey, merged) + autoscalingMinVal, err := helper.ExtractParamValue(templateMap, appBean.CustomAutoscalingMinPathKey, merged) if helper.IsNotFoundErr(err) { return 0, util.NewApiError(). WithHttpStatusCode(http.StatusPreconditionFailed). WithInternalMessage(helper.KeyNotFoundError). - WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", bean2.CustomAutoscalingMinPathKey)) + WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", appBean.CustomAutoscalingMinPathKey)) } else if err != nil { - impl.logger.Errorw("error occurred while parsing float number", "key", bean2.CustomAutoscalingMinPathKey, "err", err) + impl.logger.Errorw("error occurred while parsing float number", "key", appBean.CustomAutoscalingMinPathKey, "err", err) return 0, err } - autoscalingMaxVal, err := helper.ExtractParamValue(templateMap, bean2.CustomAutoscalingMaxPathKey, merged) + autoscalingMaxVal, err := helper.ExtractParamValue(templateMap, appBean.CustomAutoscalingMaxPathKey, merged) if helper.IsNotFoundErr(err) { return 0, util.NewApiError(). WithHttpStatusCode(http.StatusPreconditionFailed). WithInternalMessage(helper.KeyNotFoundError). - WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", bean2.CustomAutoscalingMaxPathKey)) + WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", appBean.CustomAutoscalingMaxPathKey)) } else if err != nil { - impl.logger.Errorw("error occurred while parsing float number", "key", bean2.CustomAutoscalingMaxPathKey, "err", err) + impl.logger.Errorw("error occurred while parsing float number", "key", appBean.CustomAutoscalingMaxPathKey, "err", err) return 0, err } - autoscalingReplicaCountVal, err := helper.ExtractParamValue(templateMap, bean2.CustomAutoscalingReplicaCountPathKey, merged) + autoscalingReplicaCountVal, err := helper.ExtractParamValue(templateMap, appBean.CustomAutoscalingReplicaCountPathKey, merged) if helper.IsNotFoundErr(err) { return 0, util.NewApiError(). WithHttpStatusCode(http.StatusPreconditionFailed). WithInternalMessage(helper.KeyNotFoundError). - WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", bean2.CustomAutoscalingReplicaCountPathKey)) + WithUserDetailMessage(fmt.Sprintf("empty value for key [%s]", appBean.CustomAutoscalingReplicaCountPathKey)) } else if err != nil { - impl.logger.Errorw("error occurred while parsing float number", "key", bean2.CustomAutoscalingReplicaCountPathKey, "err", err) + impl.logger.Errorw("error occurred while parsing float number", "key", appBean.CustomAutoscalingReplicaCountPathKey, "err", err) return 0, err } return helper.FetchRequiredReplicaCount(autoscalingReplicaCountVal, autoscalingMaxVal, autoscalingMinVal), nil diff --git a/pkg/deployment/manifest/bean/bean.go b/pkg/deployment/manifest/bean/bean.go index f083f113da..8820c29f9b 100644 --- a/pkg/deployment/manifest/bean/bean.go +++ b/pkg/deployment/manifest/bean/bean.go @@ -33,7 +33,7 @@ const ( ProjectNameDevtronLabel = "api.devtron.ai/project" ) -type ConfigMapAndSecretJsonV2 struct { +type GetMergedCmAndCsJsonV2Request struct { AppId int EnvId int PipeLineId int @@ -42,3 +42,9 @@ type ConfigMapAndSecretJsonV2 struct { WfrIdForDeploymentWithSpecificTrigger int Scope resourceQualifiers.Scope } + +type MergedCmAndCsJsonV2Response struct { + MergedJson []byte + ExternalCmList []string + ExternalCsList []string +} diff --git a/pkg/deployment/manifest/helper/helper.go b/pkg/deployment/manifest/helper/helper.go index 34940c66bc..caa39cb6dd 100644 --- a/pkg/deployment/manifest/helper/helper.go +++ b/pkg/deployment/manifest/helper/helper.go @@ -152,8 +152,8 @@ func GetAutoScalingReplicaCount(templateMap map[string]interface{}, appName stri } -func CreateConfigMapAndSecretJsonRequest(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride, chartVersion string, scope resourceQualifiers.Scope) bean3.ConfigMapAndSecretJsonV2 { - request := bean3.ConfigMapAndSecretJsonV2{ +func NewMergedCmAndCsJsonV2Request(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride, chartVersion string, scope resourceQualifiers.Scope) bean3.GetMergedCmAndCsJsonV2Request { + request := bean3.GetMergedCmAndCsJsonV2Request{ AppId: overrideRequest.AppId, EnvId: envOverride.TargetEnvironment, PipeLineId: overrideRequest.PipelineId, @@ -165,6 +165,14 @@ func CreateConfigMapAndSecretJsonRequest(overrideRequest *bean.ValuesOverrideReq return request } +func NewMergedCmAndCsJsonV2Response() *bean3.MergedCmAndCsJsonV2Response { + return &bean3.MergedCmAndCsJsonV2Response{ + MergedJson: []byte("{}"), + ExternalCsList: make([]string, 0), + ExternalCmList: make([]string, 0), + } +} + func GetScopeForVariables(overrideRequest *bean.ValuesOverrideRequest, envOverride *chartConfig.EnvConfigOverride) resourceQualifiers.Scope { scope := resourceQualifiers.Scope{ AppId: overrideRequest.AppId, diff --git a/pkg/deployment/trigger/devtronApps/TriggerService.go b/pkg/deployment/trigger/devtronApps/TriggerService.go index bace5ad672..c5f83a8f07 100644 --- a/pkg/deployment/trigger/devtronApps/TriggerService.go +++ b/pkg/deployment/trigger/devtronApps/TriggerService.go @@ -788,10 +788,10 @@ func (impl *TriggerServiceImpl) TriggerRelease(overrideRequest *bean3.ValuesOver valuesOverrideResponse, builtChartPath, err := impl.manifestCreationService.BuildManifestForTrigger(overrideRequest, triggeredAt, newCtx) if envDeploymentConfig == nil || (envDeploymentConfig != nil && envDeploymentConfig.Id == 0) { - envDeploymentConfig, err = impl.deploymentConfigService.GetAndMigrateConfigIfAbsentForDevtronApps(overrideRequest.AppId, overrideRequest.EnvId) - if err != nil { - impl.logger.Errorw("error in getting deployment config by appId and envId", "appId", overrideRequest.AppId, "envId", overrideRequest.EnvId, "err", err) - return releaseNo, err + envDeploymentConfig, err1 := impl.deploymentConfigService.GetAndMigrateConfigIfAbsentForDevtronApps(overrideRequest.AppId, overrideRequest.EnvId) + if err1 != nil { + impl.logger.Errorw("error in getting deployment config by appId and envId", "appId", overrideRequest.AppId, "envId", overrideRequest.EnvId, "err", err1) + return releaseNo, err1 } valuesOverrideResponse.DeploymentConfig = envDeploymentConfig } diff --git a/pkg/fluxApplication/FluxApplicationService.go b/pkg/fluxApplication/FluxApplicationService.go new file mode 100644 index 0000000000..2b03fa1665 --- /dev/null +++ b/pkg/fluxApplication/FluxApplicationService.go @@ -0,0 +1,189 @@ +package fluxApplication + +import ( + "context" + "fmt" + "github.com/devtron-labs/common-lib/utils/k8s" + "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + "github.com/devtron-labs/devtron/api/helm-app/service" + "github.com/devtron-labs/devtron/pkg/cluster" + "github.com/devtron-labs/devtron/pkg/fluxApplication/bean" + "github.com/gogo/protobuf/proto" + "go.opentelemetry.io/otel" + "go.uber.org/zap" + "net/http" +) + +type FluxApplicationService interface { + ListFluxApplications(ctx context.Context, clusterIds []int, w http.ResponseWriter) + GetFluxAppDetail(ctx context.Context, app *bean.FluxAppIdentifier) (*bean.FluxApplicationDetailDto, error) + HibernateFluxApplication(ctx context.Context, app *bean.FluxAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) + UnHibernateFluxApplication(ctx context.Context, app *bean.FluxAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) +} + +type FluxApplicationServiceImpl struct { + logger *zap.SugaredLogger + helmAppService service.HelmAppService + clusterService cluster.ClusterService + helmAppClient gRPC.HelmAppClient + pump connector.Pump +} + +func NewFluxApplicationServiceImpl(logger *zap.SugaredLogger, + helmAppService service.HelmAppService, + clusterService cluster.ClusterService, + helmAppClient gRPC.HelmAppClient, pump connector.Pump) *FluxApplicationServiceImpl { + return &FluxApplicationServiceImpl{ + logger: logger, + helmAppService: helmAppService, + clusterService: clusterService, + helmAppClient: helmAppClient, + pump: pump, + } + +} +func (impl *FluxApplicationServiceImpl) HibernateFluxApplication(ctx context.Context, app *bean.FluxAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + conf, err := impl.helmAppService.GetClusterConf(app.ClusterId) + if err != nil { + impl.logger.Errorw("HibernateFluxApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.Name) + return nil, err + } + req := service.HibernateReqAdaptor(hibernateRequest) + req.ClusterConfig = conf + res, err := impl.helmAppClient.Hibernate(ctx, req) + if err != nil { + impl.logger.Errorw("HibernateFluxApplication", "error in hibernating the requested resource", err, "clusterId", app.ClusterId, "appName", app.Name) + return nil, err + } + response := service.HibernateResponseAdaptor(res.Status) + return response, nil +} + +func (impl *FluxApplicationServiceImpl) UnHibernateFluxApplication(ctx context.Context, app *bean.FluxAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { + + conf, err := impl.helmAppService.GetClusterConf(app.ClusterId) + if err != nil { + impl.logger.Errorw("UnHibernateFluxApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.Name) + return nil, err + } + req := service.HibernateReqAdaptor(hibernateRequest) + req.ClusterConfig = conf + res, err := impl.helmAppClient.UnHibernate(ctx, req) + if err != nil { + impl.logger.Errorw("UnHibernateFluxApplication", "error in unHibernating the requested resources", err, "clusterId", app.ClusterId, "appName", app.Name) + return nil, err + } + response := service.HibernateResponseAdaptor(res.Status) + return response, nil +} + +func (impl *FluxApplicationServiceImpl) ListFluxApplications(ctx context.Context, clusterIds []int, w http.ResponseWriter) { + appStream, err := impl.listApplications(ctx, clusterIds) + + impl.pump.StartStreamWithTransformer(w, func() (proto.Message, error) { + return appStream.Recv() + }, err, + func(message interface{}) interface{} { + return impl.appListRespProtoTransformer(message.(*gRPC.FluxApplicationList)) + }) +} +func (impl *FluxApplicationServiceImpl) GetFluxAppDetail(ctx context.Context, app *bean.FluxAppIdentifier) (*bean.FluxApplicationDetailDto, error) { + config, err := impl.helmAppService.GetClusterConf(app.ClusterId) + if err != nil { + impl.logger.Errorw("error in getting cluster config", "appIdentifier", app, "err", err) + return nil, fmt.Errorf("failed to get cluster config for app %s in namespace %s: %w", app.Name, app.Namespace, err) + } + fluxDetailResponse, err := impl.getFluxAppDetailTree(ctx, config, app) + if err != nil { + impl.logger.Errorw("error in getting Flux app detail tree", "appIdentifier", app, "err", err) + return nil, fmt.Errorf("failed to get Flux app detail tree for app %s in namespace %s: %w", app.Name, app.Namespace, err) + } + + appDetail := &bean.FluxApplicationDetailDto{ + FluxApplication: &bean.FluxApplication{ + Name: app.Name, + SyncStatus: fluxDetailResponse.FluxApplication.SyncStatus, + HealthStatus: fluxDetailResponse.FluxApplication.HealthStatus, + Namespace: app.Namespace, + ClusterId: app.ClusterId, + FluxAppDeploymentType: fluxDetailResponse.FluxApplication.FluxAppDeploymentType, + ClusterName: fluxDetailResponse.FluxApplication.EnvironmentDetail.GetClusterName(), + }, + FluxAppStatusDetail: &bean.FluxAppStatusDetail{ + Status: fluxDetailResponse.FluxAppStatusDetail.GetStatus(), + Reason: fluxDetailResponse.FluxAppStatusDetail.GetReason(), + Message: fluxDetailResponse.FluxAppStatusDetail.GetMessage(), + }, + ResourceTreeResponse: fluxDetailResponse.ResourceTreeResponse, + } + + return appDetail, nil +} +func (impl *FluxApplicationServiceImpl) listApplications(ctx context.Context, clusterIds []int) (gRPC.ApplicationService_ListFluxApplicationsClient, error) { + var err error + req := &gRPC.AppListRequest{} + if len(clusterIds) == 0 { + return nil, nil + } + _, span := otel.Tracer("clusterService").Start(ctx, "FindByIds") + clusters, err := impl.clusterService.FindByIds(clusterIds) + span.End() + if err != nil { + impl.logger.Errorw("error in fetching cluster detail", "err", err) + return nil, err + } + + for _, clusterDetail := range clusters { + config := &gRPC.ClusterConfig{ + ApiServerUrl: clusterDetail.ServerUrl, + Token: clusterDetail.Config[k8s.BearerToken], + ClusterId: int32(clusterDetail.Id), + ClusterName: clusterDetail.ClusterName, + InsecureSkipTLSVerify: clusterDetail.InsecureSkipTLSVerify, + } + if clusterDetail.InsecureSkipTLSVerify == false { + config.KeyData = clusterDetail.Config[k8s.TlsKey] + config.CertData = clusterDetail.Config[k8s.CertData] + config.CaData = clusterDetail.Config[k8s.CertificateAuthorityData] + } + req.Clusters = append(req.Clusters, config) + } + applicationStream, err := impl.helmAppClient.ListFluxApplication(ctx, req) + + return applicationStream, err +} +func (impl *FluxApplicationServiceImpl) appListRespProtoTransformer(deployedApps *gRPC.FluxApplicationList) bean.FluxAppList { + appList := bean.FluxAppList{ClusterId: &[]int32{deployedApps.ClusterId}} + if deployedApps.Errored { + appList.Errored = &deployedApps.Errored + appList.ErrorMsg = &deployedApps.ErrorMsg + } else { + fluxApps := make([]bean.FluxApplication, 0, len(deployedApps.FluxApplication)) + for _, deployedapp := range deployedApps.FluxApplication { + fluxApp := bean.FluxApplication{ + Name: deployedapp.Name, + HealthStatus: deployedapp.HealthStatus, + SyncStatus: deployedapp.SyncStatus, + ClusterId: int(deployedapp.EnvironmentDetail.ClusterId), + ClusterName: deployedapp.EnvironmentDetail.ClusterName, + Namespace: deployedapp.EnvironmentDetail.Namespace, + FluxAppDeploymentType: deployedapp.FluxAppDeploymentType, + } + fluxApps = append(fluxApps, fluxApp) + } + appList.FluxApps = &fluxApps + } + + return appList +} +func (impl *FluxApplicationServiceImpl) getFluxAppDetailTree(ctx context.Context, config *gRPC.ClusterConfig, appIdentifier *bean.FluxAppIdentifier) (*gRPC.FluxAppDetail, error) { + req := &gRPC.FluxAppDetailRequest{ + ClusterConfig: config, + Namespace: appIdentifier.Namespace, + Name: appIdentifier.Name, + IsKustomizeApp: appIdentifier.IsKustomizeApp, + } + return impl.helmAppClient.GetExternalFluxAppDetail(ctx, req) +} diff --git a/pkg/fluxApplication/bean/bean.go b/pkg/fluxApplication/bean/bean.go new file mode 100644 index 0000000000..1d3c74dbc3 --- /dev/null +++ b/pkg/fluxApplication/bean/bean.go @@ -0,0 +1,43 @@ +package bean + +import "github.com/devtron-labs/devtron/api/helm-app/gRPC" + +type FluxApplicationListDto struct { + ClusterId int `json:"clusterId"` + FluxAppDto []*FluxApplication +} +type FluxApplication struct { + Name string `json:"appName"` + HealthStatus string `json:"appStatus"` + SyncStatus string `json:"syncStatus"` + ClusterId int `json:"clusterId"` + ClusterName string `json:"clusterName"` + Namespace string `json:"namespace"` + FluxAppDeploymentType string `json:"fluxAppDeploymentType"` +} + +type FluxAppList struct { + ClusterId *[]int32 `json:"clusterIds,omitempty"` + FluxApps *[]FluxApplication `json:"fluxApplication,omitempty"` + Errored *bool `json:"errored,omitempty"` + ErrorMsg *string `json:"errorMsg,omitempty"` +} + +type FluxAppIdentifier struct { + Namespace string `json:"namespace"` + Name string `json:"name"` + ClusterId int `json:"clusterId"` + IsKustomizeApp bool `json:"isKustomizeApp"` +} + +type FluxApplicationDetailDto struct { + *FluxApplication + FluxAppStatusDetail *FluxAppStatusDetail + ResourceTreeResponse *gRPC.ResourceTreeResponse `json:"resourceTree"` +} + +type FluxAppStatusDetail struct { + Status string `json:"status"` + Message string `json:"message"` + Reason string `json:"reason"` +} diff --git a/pkg/fluxApplication/helper.go b/pkg/fluxApplication/helper.go new file mode 100644 index 0000000000..5068d9ed29 --- /dev/null +++ b/pkg/fluxApplication/helper.go @@ -0,0 +1,47 @@ +package fluxApplication + +import ( + "fmt" + "github.com/devtron-labs/devtron/pkg/fluxApplication/bean" + "strconv" + "strings" +) + +/* +* appIdString contains four fields, separated by '|': +* 1. clusterId: The ID of the cluster, which is an integer value +* 2. namespace: The namespace, which is a string. +* 3. appName: The name of the Flux application (either Kustomization or HelmRelease), which is a string. +* 4. isKustomize: A boolean value indicating whether the application is of type Kustomization (true) or HelmRelease (false). +* +* +* Example: "123|my-namespace|my-app|true" +* - clusterId: "123" +* - namespace: "my-namespace" +* - appName: "my-app" +* - isKustomization: true + */ + +func DecodeFluxExternalAppId(appId string) (*bean.FluxAppIdentifier, error) { + component := strings.Split(appId, "|") + if len(component) != 4 { + return nil, fmt.Errorf("malformed app id %s", appId) + } + clusterId, err := strconv.Atoi(component[0]) + if err != nil { + return nil, err + } + isKustomizeApp, err := strconv.ParseBool(component[3]) + if err != nil { + return nil, err + } + if clusterId <= 0 { + return nil, fmt.Errorf("target cluster is not provided") + } + return &bean.FluxAppIdentifier{ + ClusterId: clusterId, + Namespace: component[1], + Name: component[2], + IsKustomizeApp: isKustomizeApp, + }, nil +} diff --git a/pkg/k8s/K8sCommonService.go b/pkg/k8s/K8sCommonService.go index e9d55b3603..09717b059b 100644 --- a/pkg/k8s/K8sCommonService.go +++ b/pkg/k8s/K8sCommonService.go @@ -24,19 +24,20 @@ import ( k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/api/bean" helmBean "github.com/devtron-labs/devtron/api/helm-app/service/bean" - util2 "github.com/devtron-labs/devtron/internal/util" + internalUtil "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/argoApplication" "github.com/devtron-labs/devtron/pkg/cluster" bean3 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" "github.com/devtron-labs/devtron/util" "go.opentelemetry.io/otel" "go.uber.org/zap" + apiV1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" + clientV1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/rest" "net/http" "strconv" @@ -46,17 +47,20 @@ import ( type K8sCommonService interface { GetResource(ctx context.Context, request *ResourceRequestBean) (resp *ResourceGetResponse, err error) + GetDataFromConfigMaps(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.ConfigMap, error) + GetDataFromSecrets(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.Secret, error) UpdateResource(ctx context.Context, request *ResourceRequestBean) (resp *k8s.ManifestResponse, err error) DeleteResource(ctx context.Context, request *ResourceRequestBean) (resp *k8s.ManifestResponse, err error) ListEvents(ctx context.Context, request *ResourceRequestBean) (*k8s.EventsResponse, error) GetRestConfigByClusterId(ctx context.Context, clusterId int) (*rest.Config, error, *cluster.ClusterBean) GetManifestsByBatch(ctx context.Context, request []ResourceRequestBean) ([]BatchResourceResponse, error) - FilterK8sResources(ctx context.Context, resourceTreeInf map[string]interface{}, appDetail bean.AppDetailContainer, appId string, kindsToBeFiltered []string) []ResourceRequestBean + FilterK8sResources(ctx context.Context, resourceTreeInf map[string]interface{}, appDetail bean.AppDetailContainer, appId string, kindsToBeFiltered []string, externalArgoAppName string) []ResourceRequestBean RotatePods(ctx context.Context, request *RotatePodRequest) (*RotatePodResponse, error) - GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *v1.CoreV1Client, error) - GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *v1.CoreV1Client, error) + GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) + GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) GetK8sServerVersion(clusterId int) (*version.Info, error) PortNumberExtraction(resp []BatchResourceResponse, resourceTree map[string]interface{}) map[string]interface{} + GetRestConfigOfCluster(ctx context.Context, request *ResourceRequestBean) (*rest.Config, error) GetK8sConfigAndClients(ctx context.Context, cluster *cluster.ClusterBean) (*rest.Config, *http.Client, *kubernetes.Clientset, error) GetK8sConfigAndClientsByClusterId(ctx context.Context, clusterId int) (*rest.Config, *http.Client, *kubernetes.Clientset, error) GetPreferredVersionForAPIGroup(ctx context.Context, clusterId int, groupName string) (string, error) @@ -95,23 +99,13 @@ func (impl *K8sCommonServiceImpl) GetResource(ctx context.Context, request *Reso clusterId := request.ClusterId //getting rest config by clusterId resourceIdentifier := request.K8sRequest.ResourceIdentifier - var restConfigFinal *rest.Config - if len(request.ExternalArgoApplicationName) > 0 { - restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) - if err != nil { - impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) - return nil, err - } - restConfigFinal = restConfig - } else { - restConfig, err, _ := impl.GetRestConfigByClusterId(ctx, clusterId) - if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) - return nil, err - } - restConfigFinal = restConfig + + restConfig, err := impl.GetRestConfigOfCluster(ctx, request) + if err != nil { + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) + return nil, err } - resp, err := impl.K8sUtil.GetResource(ctx, resourceIdentifier.Namespace, resourceIdentifier.Name, resourceIdentifier.GroupVersionKind, restConfigFinal) + resp, err := impl.K8sUtil.GetResource(ctx, resourceIdentifier.Namespace, resourceIdentifier.Name, resourceIdentifier.GroupVersionKind, restConfig) if err != nil { impl.logger.Errorw("error in getting resource", "err", err, "resource", resourceIdentifier.Name) return nil, err @@ -122,33 +116,102 @@ func (impl *K8sCommonServiceImpl) GetResource(ctx context.Context, request *Reso return response, nil } +func (impl *K8sCommonServiceImpl) GetDataFromConfigMaps(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.ConfigMap, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "K8sCommonServiceImpl.GetDataFromConfigMaps") + defer span.End() + response := make(map[string]*apiV1.ConfigMap, len(request.GetExternalCmList())) + if len(request.GetExternalCmList()) == 0 { + return response, nil + } + _, v1Client, err := impl.GetCoreClientByClusterId(request.GetClusterId()) + if err != nil { + impl.logger.Errorw("error in getting coreV1 client by clusterId", "clusterId", request.clusterId, "err", err) + return nil, err + } + // using for loop instead of getting all configMaps at once since request.GetExternalCmList() will be small + for _, cmName := range request.GetExternalCmList() { + configMap, err := impl.K8sUtil.GetConfigMapWithCtx(newCtx, request.GetNamespace(), cmName, v1Client) + if err != nil { + impl.logger.Errorw("error in getting configMap", "namespace", request.GetNamespace(), "cmName", cmName, "err", err) + return nil, err + } + response[cmName] = configMap + } + return response, nil +} + +func (impl *K8sCommonServiceImpl) GetDataFromSecrets(ctx context.Context, request *CmCsRequestBean) (map[string]*apiV1.Secret, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "K8sCommonServiceImpl.GetDataFromConfigMaps") + defer span.End() + response := make(map[string]*apiV1.Secret, len(request.GetExternalCmList())) + if len(request.GetExternalCsList()) == 0 { + return response, nil + } + _, v1Client, err := impl.GetCoreClientByClusterId(request.GetClusterId()) + if err != nil { + impl.logger.Errorw("error in getting coreV1 client by clusterId", "clusterId", request.clusterId, "err", err) + return nil, err + } + // using for loop instead of getting all secrets at once since request.GetExternalCsList() will be small + for _, csName := range request.GetExternalCsList() { + secret, err := impl.K8sUtil.GetSecretWithCtx(newCtx, request.GetNamespace(), csName, v1Client) + if err != nil { + impl.logger.Errorw("error in getting configMap", "namespace", request.namespace, "csName", csName, "err", err) + return nil, err + } + response[csName] = secret + } + return response, nil +} + func (impl *K8sCommonServiceImpl) UpdateResource(ctx context.Context, request *ResourceRequestBean) (*k8s.ManifestResponse, error) { //getting rest config by clusterId clusterId := request.ClusterId - restConfig, err, _ := impl.GetRestConfigByClusterId(ctx, clusterId) + + resourceIdentifier := request.K8sRequest.ResourceIdentifier + + restConfig, err := impl.GetRestConfigOfCluster(ctx, request) if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) return nil, err } - resourceIdentifier := request.K8sRequest.ResourceIdentifier resp, err := impl.K8sUtil.UpdateResource(ctx, restConfig, resourceIdentifier.GroupVersionKind, resourceIdentifier.Namespace, request.K8sRequest.Patch) if err != nil { impl.logger.Errorw("error in updating resource", "err", err, "clusterId", clusterId) statusError, ok := err.(*errors.StatusError) if ok { - err = &util2.ApiError{Code: "400", HttpStatusCode: int(statusError.ErrStatus.Code), UserMessage: statusError.Error()} + err = &internalUtil.ApiError{Code: "400", HttpStatusCode: int(statusError.ErrStatus.Code), UserMessage: statusError.Error()} } return nil, err } return resp, nil } +func (impl *K8sCommonServiceImpl) GetRestConfigOfCluster(ctx context.Context, request *ResourceRequestBean) (*rest.Config, error) { + //getting rest config by clusterId + clusterId := request.ClusterId + if len(request.ExternalArgoApplicationName) > 0 { + restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) + if err != nil { + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) + return nil, err + } + return restConfig, nil + } else { + restConfig, err, _ := impl.GetRestConfigByClusterId(ctx, clusterId) + if err != nil { + impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) + return nil, err + } + return restConfig, nil + } +} func (impl *K8sCommonServiceImpl) DeleteResource(ctx context.Context, request *ResourceRequestBean) (*k8s.ManifestResponse, error) { //getting rest config by clusterId clusterId := request.ClusterId - restConfig, err, _ := impl.GetRestConfigByClusterId(ctx, clusterId) + restConfig, err := impl.GetRestConfigOfCluster(ctx, request) if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) return nil, err } resourceIdentifier := request.K8sRequest.ResourceIdentifier @@ -161,34 +224,23 @@ func (impl *K8sCommonServiceImpl) DeleteResource(ctx context.Context, request *R } func (impl *K8sCommonServiceImpl) ListEvents(ctx context.Context, request *ResourceRequestBean) (*k8s.EventsResponse, error) { - clusterId := request.ClusterId resourceIdentifier := request.K8sRequest.ResourceIdentifier - var restConfigFinal *rest.Config - if len(request.ExternalArgoApplicationName) > 0 { - restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) - if err != nil { - impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) - return nil, err - } - restConfigFinal = restConfig - } else { - restConfig, err, _ := impl.GetRestConfigByClusterId(ctx, clusterId) - if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) - return nil, err - } - restConfigFinal = restConfig + restConfig, err := impl.GetRestConfigOfCluster(ctx, request) + if err != nil { + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", request.ClusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) + return nil, err } - list, err := impl.K8sUtil.ListEvents(restConfigFinal, resourceIdentifier.Namespace, resourceIdentifier.GroupVersionKind, ctx, resourceIdentifier.Name) + + list, err := impl.K8sUtil.ListEvents(restConfig, resourceIdentifier.Namespace, resourceIdentifier.GroupVersionKind, ctx, resourceIdentifier.Name) if err != nil { - impl.logger.Errorw("error in listing events", "err", err, "clusterId", clusterId) + impl.logger.Errorw("error in listing events", "err", err, "clusterId", request.ClusterId) return nil, err } return &k8s.EventsResponse{list}, nil } -func (impl *K8sCommonServiceImpl) FilterK8sResources(ctx context.Context, resourceTree map[string]interface{}, appDetail bean.AppDetailContainer, appId string, kindsToBeFiltered []string) []ResourceRequestBean { +func (impl *K8sCommonServiceImpl) FilterK8sResources(ctx context.Context, resourceTree map[string]interface{}, appDetail bean.AppDetailContainer, appId string, kindsToBeFiltered []string, externalArgoAppName string) []ResourceRequestBean { validRequests := make([]ResourceRequestBean, 0) kindsToBeFilteredMap := util.ConvertStringSliceToMap(kindsToBeFiltered) resourceTreeNodes, ok := resourceTree["nodes"] @@ -227,6 +279,7 @@ func (impl *K8sCommonServiceImpl) FilterK8sResources(ctx context.Context, resour }, }, }, + ExternalArgoApplicationName: externalArgoAppName, } validRequests = append(validRequests, req) } @@ -380,7 +433,7 @@ func (impl *K8sCommonServiceImpl) GetK8sServerVersion(clusterId int) (*version.I return k8sVersion, err } -func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *v1.CoreV1Client, error) { +func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) { clusterBean, err := impl.clusterService.FindById(clusterId) if err != nil { impl.logger.Errorw("error occurred in finding clusterBean by Id", "clusterId", clusterId, "err", err) @@ -403,7 +456,7 @@ func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kube return clientSet, v1Client, nil } -func (impl *K8sCommonServiceImpl) GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *v1.CoreV1Client, error) { +func (impl *K8sCommonServiceImpl) GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) { restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) if err != nil { impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", req.ClusterId, "externalArgoApplicationName", req.ExternalArgoApplicationName) diff --git a/pkg/k8s/application/bean/bean.go b/pkg/k8s/application/bean/bean.go index cdf71e5cdb..7afd74a0a3 100644 --- a/pkg/k8s/application/bean/bean.go +++ b/pkg/k8s/application/bean/bean.go @@ -20,6 +20,10 @@ import ( "github.com/devtron-labs/common-lib/utils/k8s" ) +const ( + InvalidAppId = "invalid app id" + AppIdDecodingError = "error in decoding appId" +) const ( DEFAULT_NAMESPACE = "default" EVENT_K8S_KIND = "Event" @@ -32,9 +36,11 @@ const ( DevtronAppType = 0 // Identifier for Devtron Apps HelmAppType = 1 // Identifier for Helm Apps ArgoAppType = 2 + FluxAppType = 3 //Identifier for Flux Apps // Deployment Type Identifiers HelmInstalledType = 0 // Identifier for Helm deployment ArgoInstalledType = 1 // Identifier for ArgoCD deployment + FluxInstalledType = 2 //identifier for fluxCd Deployment ) const ( diff --git a/pkg/k8s/application/k8sApplicationService.go b/pkg/k8s/application/k8sApplicationService.go index 1141b9c551..39b1902b17 100644 --- a/pkg/k8s/application/k8sApplicationService.go +++ b/pkg/k8s/application/k8sApplicationService.go @@ -25,8 +25,11 @@ import ( "github.com/devtron-labs/devtron/api/helm-app/gRPC" client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/api/helm-app/service/bean" + bean4 "github.com/devtron-labs/devtron/pkg/argoApplication/bean" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" clientErrors "github.com/devtron-labs/devtron/pkg/errors" + "github.com/devtron-labs/devtron/pkg/fluxApplication" + bean2 "github.com/devtron-labs/devtron/pkg/fluxApplication/bean" "io" v1 "k8s.io/client-go/kubernetes/typed/core/v1" "net/http" @@ -86,6 +89,8 @@ type K8sApplicationService interface { RecreateResource(ctx context.Context, request *k8s.ResourceRequestBean) (*k8s2.ManifestResponse, error) DeleteResourceWithAudit(ctx context.Context, request *k8s.ResourceRequestBean, userId int32) (*k8s2.ManifestResponse, error) GetUrlsByBatchForIngress(ctx context.Context, resp []k8s.BatchResourceResponse) []interface{} + ValidateFluxResourceRequest(ctx context.Context, appIdentifier *bean2.FluxAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) + ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean4.ArgoAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) } type K8sApplicationServiceImpl struct { @@ -102,13 +107,14 @@ type K8sApplicationServiceImpl struct { ephemeralContainerRepository repository.EphemeralContainersRepository ephemeralContainerConfig *EphemeralContainerConfig argoApplicationService argoApplication.ArgoApplicationService + fluxApplicationService fluxApplication.FluxApplicationService } func NewK8sApplicationServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.ClusterService, pump connector.Pump, helmAppService client.HelmAppService, K8sUtil *k8s2.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, K8sResourceHistoryService kubernetesResourceAuditLogs.K8sResourceHistoryService, k8sCommonService k8s.K8sCommonService, terminalSession terminal.TerminalSessionHandler, ephemeralContainerService cluster.EphemeralContainerService, ephemeralContainerRepository repository.EphemeralContainersRepository, - argoApplicationService argoApplication.ArgoApplicationService) (*K8sApplicationServiceImpl, error) { + argoApplicationService argoApplication.ArgoApplicationService, fluxApplicationService fluxApplication.FluxApplicationService) (*K8sApplicationServiceImpl, error) { ephemeralContainerConfig := &EphemeralContainerConfig{} err := env.Parse(ephemeralContainerConfig) if err != nil { @@ -129,6 +135,7 @@ func NewK8sApplicationServiceImpl(Logger *zap.SugaredLogger, clusterService clus ephemeralContainerRepository: ephemeralContainerRepository, ephemeralContainerConfig: ephemeralContainerConfig, argoApplicationService: argoApplicationService, + fluxApplicationService: fluxApplicationService, }, nil } @@ -181,6 +188,13 @@ func (impl *K8sApplicationServiceImpl) ValidatePodLogsRequestQuery(r *http.Reque } sinceTime = metav1.Unix(sinceTimeVar, 0) } + + namespace := v.Get("namespace") + if namespace == "" { + err = fmt.Errorf("missing required field namespace") + impl.logger.Errorw("empty namespace", "err", err, "appId", request.AppId) + return nil, err + } containerName, clusterIdString := v.Get("containerName"), v.Get("clusterId") prevContainerLogs := v.Get("previous") isPrevLogs, err := strconv.ParseBool(prevContainerLogs) @@ -220,43 +234,59 @@ func (impl *K8sApplicationServiceImpl) ValidatePodLogsRequestQuery(r *http.Reque } request.K8sRequest = k8sRequest if appId != "" { - if len(appTypeStr) > 0 && !(appType == bean3.DevtronAppType || appType == bean3.HelmAppType || appType == bean3.ArgoAppType) { + if len(appTypeStr) > 0 && !request.IsValidAppType() { impl.logger.Errorw("Invalid appType", "err", err, "appType", appType) return nil, err } // Validate Deployment Type deploymentType, err := strconv.Atoi(v.Get("deploymentType")) - if err != nil || !(deploymentType == bean3.HelmInstalledType || deploymentType == bean3.ArgoInstalledType) { + if err != nil || !request.IsValidDeploymentType() { impl.logger.Errorw("Invalid deploymentType", "err", err, "deploymentType", deploymentType) return nil, err } + + //handle the ns coming for the requested resource request.DeploymentType = deploymentType // Validate App Id - if request.AppType == bean3.HelmAppType { + if request.AppType == bean3.ArgoAppType { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(appId) + if err != nil { + impl.logger.Errorw(bean3.AppIdDecodingError, "err", err, "appId", appId) + return nil, err + } + + request.ClusterId = appIdentifier.ClusterId + request.K8sRequest.ResourceIdentifier.Namespace = namespace + request.AppId = appId + } else if request.AppType == bean3.HelmAppType { // For Helm App resources appIdentifier, err := impl.helmAppService.DecodeAppId(appId) if err != nil { - impl.logger.Errorw("error in decoding appId", "err", err, "appId", appId) + impl.logger.Errorw(bean3.AppIdDecodingError, "err", err, "appId", appId) return nil, err } request.AppIdentifier = appIdentifier request.ClusterId = appIdentifier.ClusterId - request.K8sRequest.ResourceIdentifier.Namespace = appIdentifier.Namespace + request.K8sRequest.ResourceIdentifier.Namespace = namespace } else if request.AppType == bean3.DevtronAppType { // For Devtron App resources devtronAppIdentifier, err := impl.DecodeDevtronAppId(appId) if err != nil { - impl.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) + impl.logger.Errorw(bean3.AppIdDecodingError, "err", err, "appId", request.AppId) return nil, err } request.DevtronAppIdentifier = devtronAppIdentifier request.ClusterId = devtronAppIdentifier.ClusterId - namespace := v.Get("namespace") - if namespace == "" { - err = fmt.Errorf("missing required field namespace") - impl.logger.Errorw("empty namespace", "err", err, "appId", request.AppId) + request.K8sRequest.ResourceIdentifier.Namespace = namespace + } else if request.AppType == bean3.FluxAppType { + // For flux App resources + appIdentifier, err := fluxApplication.DecodeFluxExternalAppId(appId) + if err != nil { + impl.logger.Errorw(bean3.AppIdDecodingError, "err", err, "appId", appId) return nil, err } + request.ExternalFluxAppIdentifier = appIdentifier + request.ClusterId = appIdentifier.ClusterId request.K8sRequest.ResourceIdentifier.Namespace = namespace } } else if clusterIdString != "" { @@ -267,12 +297,6 @@ func (impl *K8sApplicationServiceImpl) ValidatePodLogsRequestQuery(r *http.Reque return nil, err } request.ClusterId = clusterId - namespace := v.Get("namespace") - if namespace == "" { - err = fmt.Errorf("missing required field namespace") - impl.logger.Errorw("empty namespace", "err", err, "appId", request.AppId) - return nil, err - } request.K8sRequest.ResourceIdentifier.Namespace = namespace request.K8sRequest.ResourceIdentifier.GroupVersionKind = schema.GroupVersionKind{ Group: "", @@ -292,20 +316,21 @@ func (impl *K8sApplicationServiceImpl) ValidateTerminalRequestQuery(r *http.Requ request.PodName = vars["pod"] request.Shell = vars["shell"] resourceRequestBean := &k8s.ResourceRequestBean{} - resourceRequestBean.ExternalArgoApplicationName = v.Get("externalArgoApplicationName") identifier := vars["identifier"] if strings.Contains(identifier, "|") { // Validate App Type appType, err := strconv.Atoi(v.Get("appType")) - if err != nil || appType < bean3.DevtronAppType && appType > bean3.HelmAppType { + resourceRequestBean.AppType = appType + if err != nil || !resourceRequestBean.IsValidAppType() { impl.logger.Errorw("Invalid appType", "err", err, "appType", appType) return nil, nil, err } request.ApplicationId = identifier + if appType == bean3.HelmAppType { appIdentifier, err := impl.helmAppService.DecodeAppId(request.ApplicationId) if err != nil { - impl.logger.Errorw("invalid app id", "err", err, "appId", request.ApplicationId) + impl.logger.Errorw(bean3.InvalidAppId, "err", err, "appId", request.ApplicationId) return nil, nil, err } resourceRequestBean.AppIdentifier = appIdentifier @@ -314,22 +339,42 @@ func (impl *K8sApplicationServiceImpl) ValidateTerminalRequestQuery(r *http.Requ } else if appType == bean3.DevtronAppType { devtronAppIdentifier, err := impl.DecodeDevtronAppId(request.ApplicationId) if err != nil { - impl.logger.Errorw("invalid app id", "err", err, "appId", request.ApplicationId) + impl.logger.Errorw(bean3.InvalidAppId, "err", err, "appId", request.ApplicationId) return nil, nil, err } resourceRequestBean.DevtronAppIdentifier = devtronAppIdentifier resourceRequestBean.ClusterId = devtronAppIdentifier.ClusterId request.ClusterId = devtronAppIdentifier.ClusterId + } else if appType == bean3.FluxAppType { + fluxAppIdentifier, err := fluxApplication.DecodeFluxExternalAppId(request.ApplicationId) + if err != nil { + impl.logger.Errorw(bean3.InvalidAppId, "err", err, "appId", request.ApplicationId) + return nil, nil, err + } + resourceRequestBean.ExternalFluxAppIdentifier = fluxAppIdentifier + resourceRequestBean.ClusterId = fluxAppIdentifier.ClusterId + request.ClusterId = fluxAppIdentifier.ClusterId + + } else if appType == bean3.ArgoAppType { + appIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.ApplicationId) + if err != nil { + impl.logger.Errorw(bean3.InvalidAppId, "err", err, "appId", request.ApplicationId) + return nil, nil, err + } + resourceRequestBean.ExternalArgoApplicationName = appIdentifier.AppName + resourceRequestBean.ClusterId = appIdentifier.ClusterId + request.ClusterId = appIdentifier.ClusterId + //request.ExternalArgoApplicationName = appIdentifier.AppName } } else { // Validate Cluster Id - clsuterId, err := strconv.Atoi(identifier) - if err != nil || clsuterId <= 0 { + clusterId, err := strconv.Atoi(identifier) + if err != nil || clusterId <= 0 { impl.logger.Errorw("Invalid cluster id", "err", err, "clusterId", identifier) return nil, nil, err } - resourceRequestBean.ClusterId = clsuterId - request.ClusterId = clsuterId + resourceRequestBean.ClusterId = clusterId + request.ClusterId = clusterId k8sRequest := &k8s2.K8sRequestBean{ ResourceIdentifier: k8s2.ResourceIdentifier{ Name: request.PodName, @@ -377,22 +422,12 @@ func (impl *K8sApplicationServiceImpl) GetPodLogs(ctx context.Context, request * clusterId := request.ClusterId resourceIdentifier := request.K8sRequest.ResourceIdentifier podLogsRequest := request.K8sRequest.PodLogsRequest - var restConfigFinal *rest.Config - if len(request.ExternalArgoApplicationName) > 0 { - restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) - if err != nil { - impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) - } - restConfigFinal = restConfig - } else { - restConfig, err, _ := impl.k8sCommonService.GetRestConfigByClusterId(ctx, clusterId) - if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterId) - return nil, err - } - restConfigFinal = restConfig + + restConfig, err := impl.k8sCommonService.GetRestConfigOfCluster(ctx, request) + if err != nil { + impl.logger.Errorw("error in getting rest config by clusterId", "err", err, "clusterId", clusterId, "") } - resp, err := impl.K8sUtil.GetPodLogs(ctx, restConfigFinal, resourceIdentifier.Name, resourceIdentifier.Namespace, podLogsRequest.SinceTime, podLogsRequest.TailLines, podLogsRequest.SinceSeconds, podLogsRequest.Follow, podLogsRequest.ContainerName, podLogsRequest.IsPrevContainerLogsEnabled) + resp, err := impl.K8sUtil.GetPodLogs(ctx, restConfig, resourceIdentifier.Name, resourceIdentifier.Namespace, podLogsRequest.SinceTime, podLogsRequest.TailLines, podLogsRequest.SinceSeconds, podLogsRequest.Follow, podLogsRequest.ContainerName, podLogsRequest.IsPrevContainerLogsEnabled) if err != nil { impl.logger.Errorw("error in getting pod logs", "err", err, "clusterId", clusterId) return nil, err @@ -487,6 +522,72 @@ func (impl *K8sApplicationServiceImpl) validateResourceRequest(ctx context.Conte } return impl.validateContainerNameIfReqd(valid, request, app), nil } +func (impl *K8sApplicationServiceImpl) ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean4.ArgoAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) { + app, err := impl.argoApplicationService.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) + if err != nil { + impl.logger.Errorw("error in getting app detail", "err", err, "appDetails", appIdentifier) + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + return false, err + } + + valid := false + + for _, node := range app.ResourceTree.Nodes { + nodeDetails := k8s2.ResourceIdentifier{ + Name: node.Name, + Namespace: node.Namespace, + GroupVersionKind: schema.GroupVersionKind{ + Group: node.Group, + Version: node.Version, + Kind: node.Kind, + }, + } + if nodeDetails == request.ResourceIdentifier { + valid = true + break + } + } + appDetail := &gRPC.AppDetail{ + ResourceTreeResponse: app.ResourceTree, + } + return impl.validateContainerNameIfReqd(valid, request, appDetail), nil +} + +func (impl *K8sApplicationServiceImpl) ValidateFluxResourceRequest(ctx context.Context, appIdentifier *bean2.FluxAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) { + app, err := impl.fluxApplicationService.GetFluxAppDetail(ctx, appIdentifier) + if err != nil { + impl.logger.Errorw("error in getting app detail", "err", err, "appDetails", appIdentifier) + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + return false, err + } + + valid := false + for _, node := range app.ResourceTreeResponse.Nodes { + nodeDetails := k8s2.ResourceIdentifier{ + Name: node.Name, + Namespace: node.Namespace, + GroupVersionKind: schema.GroupVersionKind{ + Group: node.Group, + Version: node.Version, + Kind: node.Kind, + }, + } + if nodeDetails == request.ResourceIdentifier { + valid = true + break + } + } + appDetail := &gRPC.AppDetail{ + ResourceTreeResponse: app.ResourceTreeResponse, + } + return impl.validateContainerNameIfReqd(valid, request, appDetail), nil +} func (impl *K8sApplicationServiceImpl) validateContainerNameIfReqd(valid bool, request *k8s2.K8sRequestBean, app *gRPC.AppDetail) bool { if !valid { diff --git a/pkg/k8s/bean.go b/pkg/k8s/bean.go index 3c3a6501f5..a39fba2ee8 100644 --- a/pkg/k8s/bean.go +++ b/pkg/k8s/bean.go @@ -19,18 +19,77 @@ package k8s import ( "github.com/devtron-labs/common-lib/utils/k8s" helmBean "github.com/devtron-labs/devtron/api/helm-app/service/bean" + bean2 "github.com/devtron-labs/devtron/pkg/fluxApplication/bean" "github.com/devtron-labs/devtron/pkg/k8s/application/bean" ) type ResourceRequestBean struct { AppId string `json:"appId"` - AppType int `json:"appType,omitempty"` // 0: DevtronApp, 1: HelmApp, 2:ArgoApp + AppType int `json:"appType,omitempty"` // 0: DevtronApp, 1: HelmApp, 2:ArgoApp, 3 fluxApp DeploymentType int `json:"deploymentType,omitempty"` // 0: DevtronApp, 1: HelmApp AppIdentifier *helmBean.AppIdentifier `json:"-"` K8sRequest *k8s.K8sRequestBean `json:"k8sRequest"` DevtronAppIdentifier *bean.DevtronAppIdentifier `json:"-"` // For Devtron App Resources ClusterId int `json:"clusterId"` // clusterId is used when request is for direct cluster (not for helm release) ExternalArgoApplicationName string `json:"externalArgoApplicationName,omitempty"` + ExternalFluxAppIdentifier *bean2.FluxAppIdentifier `json: "-"` +} + +func (r *ResourceRequestBean) IsValidAppType() bool { + return r.AppType == bean.DevtronAppType || r.AppType == bean.HelmAppType || r.AppType == bean.ArgoAppType || r.AppType == bean.FluxAppType +} + +func (r *ResourceRequestBean) IsValidDeploymentType() bool { + return r.DeploymentType == bean.HelmInstalledType || r.DeploymentType == bean.ArgoInstalledType || r.DeploymentType == bean.FluxInstalledType +} + +type CmCsRequestBean struct { + clusterId int + namespace string + externalCmList []string + externalCsList []string +} + +func (req *CmCsRequestBean) SetClusterId(clusterId int) *CmCsRequestBean { + req.clusterId = clusterId + return req +} + +func (req *CmCsRequestBean) SetNamespace(namespace string) *CmCsRequestBean { + req.namespace = namespace + return req +} + +func (req *CmCsRequestBean) SetExternalCmList(externalCmList ...string) *CmCsRequestBean { + if len(externalCmList) == 0 { + return req + } + req.externalCmList = append(req.externalCmList, externalCmList...) + return req +} + +func (req *CmCsRequestBean) SetExternalCsList(externalCsList ...string) *CmCsRequestBean { + if len(externalCsList) == 0 { + return req + } + req.externalCsList = append(req.externalCsList, externalCsList...) + return req +} + +func (req *CmCsRequestBean) GetClusterId() int { + return req.clusterId +} + +func (req *CmCsRequestBean) GetNamespace() string { + return req.namespace +} + +func (req *CmCsRequestBean) GetExternalCmList() []string { + return req.externalCmList +} + +func (req *CmCsRequestBean) GetExternalCsList() []string { + return req.externalCsList } type LogsDownloadBean struct { diff --git a/pkg/k8s/helper.go b/pkg/k8s/helper.go index b49c5f756b..1213fb9fa7 100644 --- a/pkg/k8s/helper.go +++ b/pkg/k8s/helper.go @@ -20,6 +20,8 @@ import ( "errors" "fmt" "github.com/Masterminds/semver" + "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/fluxApplication" k8sErrors "k8s.io/apimachinery/pkg/api/errors" "strings" ) @@ -43,6 +45,24 @@ func GetClientErrorMessage(err error) string { return err.Error() } +func ParseK8sClientErrorToApiError(err error) *util.ApiError { + if apiErr := (&util.ApiError{}); errors.As(err, &apiErr) { + // do not change the error if it is already an ApiError + return apiErr + } + // if error is of type k8sErrors.APIStatus, then extract the message from it + if status, ok := err.(k8sErrors.APIStatus); ok || errors.As(err, &status) { + return util.NewApiError(). + WithHttpStatusCode(int(status.Status().Code)). + WithUserDetailMessage(status.Status().Message). + WithInternalMessage(status.Status().Message) + } + // generic error + return util.NewApiError(). + WithUserDetailMessage(err.Error()). + WithInternalMessage(err.Error()) +} + // StripPrereleaseFromK8sVersion takes in k8sVersion and stripe pre-release from semver version and return sanitized k8sVersion // or error if invalid version provided, e.g. if k8sVersion = "1.25.16-eks-b9c9ed7", then it returns "1.25.16". func StripPrereleaseFromK8sVersion(k8sVersion string) string { @@ -57,3 +77,16 @@ func StripPrereleaseFromK8sVersion(k8sVersion string) string { } return k8sVersion } + +func NewCmCsRequestBean(clusterId int, namespace string) *CmCsRequestBean { + req := &CmCsRequestBean{} + return req.SetClusterId(clusterId).SetNamespace(namespace) +} + +func IsClusterStringContainsFluxField(str string) bool { + _, err := fluxApplication.DecodeFluxExternalAppId(str) + if err != nil { + return false + } + return true +} diff --git a/pkg/k8s/informer/K8sInformerFactory.go b/pkg/k8s/informer/K8sInformerFactory.go index 7ddc92f08c..bc9739e9df 100644 --- a/pkg/k8s/informer/K8sInformerFactory.go +++ b/pkg/k8s/informer/K8sInformerFactory.go @@ -18,25 +18,23 @@ package informer import ( "github.com/devtron-labs/common-lib/utils/k8s" - "sync" - "time" - "github.com/devtron-labs/devtron/api/bean" "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/tools/cache" + "sync" + "time" ) -func NewGlobalMapClusterNamespace() map[string]map[string]bool { - globalMapClusterNamespace := make(map[string]map[string]bool) +func NewGlobalMapClusterNamespace() sync.Map { + var globalMapClusterNamespace sync.Map return globalMapClusterNamespace } type K8sInformerFactoryImpl struct { logger *zap.SugaredLogger - globalMapClusterNamespace map[string]map[string]bool // {"cluster1":{"ns1":true","ns2":true"}} - mutex sync.Mutex + globalMapClusterNamespace sync.Map // {"cluster1":{"ns1":true","ns2":true"}} informerStopper map[string]chan struct{} k8sUtil *k8s.K8sServiceImpl } @@ -47,7 +45,7 @@ type K8sInformerFactory interface { CleanNamespaceInformer(clusterName string) } -func NewK8sInformerFactoryImpl(logger *zap.SugaredLogger, globalMapClusterNamespace map[string]map[string]bool, k8sUtil *k8s.K8sServiceImpl) *K8sInformerFactoryImpl { +func NewK8sInformerFactoryImpl(logger *zap.SugaredLogger, globalMapClusterNamespace sync.Map, k8sUtil *k8s.K8sServiceImpl) *K8sInformerFactoryImpl { informerFactory := &K8sInformerFactoryImpl{ logger: logger, globalMapClusterNamespace: globalMapClusterNamespace, @@ -59,19 +57,17 @@ func NewK8sInformerFactoryImpl(logger *zap.SugaredLogger, globalMapClusterNamesp func (impl *K8sInformerFactoryImpl) GetLatestNamespaceListGroupByCLuster() map[string]map[string]bool { copiedClusterNamespaces := make(map[string]map[string]bool) - for key, value := range impl.globalMapClusterNamespace { - for namespace, v := range value { - if _, ok := copiedClusterNamespaces[key]; !ok { - allNamespaces := make(map[string]bool) - allNamespaces[namespace] = v - copiedClusterNamespaces[key] = allNamespaces - } else { - allNamespaces := copiedClusterNamespaces[key] - allNamespaces[namespace] = v - copiedClusterNamespaces[key] = allNamespaces - } - } - } + impl.globalMapClusterNamespace.Range(func(key, value interface{}) bool { + clusterName := key.(string) + allNamespaces := value.(*sync.Map) + namespaceMap := make(map[string]bool) + allNamespaces.Range(func(nsKey, nsValue interface{}) bool { + namespaceMap[nsKey.(string)] = nsValue.(bool) + return true + }) + copiedClusterNamespaces[clusterName] = namespaceMap + return true + }) return copiedClusterNamespaces } @@ -86,14 +82,14 @@ func (impl *K8sInformerFactoryImpl) BuildInformer(clusterInfo []*bean.ClusterInf CertData: info.CertData, CAData: info.CAData, } - impl.buildInformerAndNamespaceList(info.ClusterName, clusterConfig, &impl.mutex) + impl.buildInformerAndNamespaceList(info.ClusterName, clusterConfig) } return } -func (impl *K8sInformerFactoryImpl) buildInformerAndNamespaceList(clusterName string, clusterConfig *k8s.ClusterConfig, mutex *sync.Mutex) map[string]map[string]bool { - allNamespaces := make(map[string]bool) - impl.globalMapClusterNamespace[clusterName] = allNamespaces +func (impl *K8sInformerFactoryImpl) buildInformerAndNamespaceList(clusterName string, clusterConfig *k8s.ClusterConfig) sync.Map { + allNamespaces := sync.Map{} + impl.globalMapClusterNamespace.Store(clusterName, &allNamespaces) _, _, clusterClient, err := impl.k8sUtil.GetK8sConfigAndClients(clusterConfig) if err != nil { impl.logger.Errorw("error in getting k8s clientset", "err", err, "clusterName", clusterConfig.ClusterName) @@ -105,30 +101,16 @@ func (impl *K8sInformerFactoryImpl) buildInformerAndNamespaceList(clusterName st nsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if mobject, ok := obj.(metav1.Object); ok { - mutex.Lock() - defer mutex.Unlock() - if _, ok := impl.globalMapClusterNamespace[clusterName]; !ok { - allNamespaces := make(map[string]bool) - allNamespaces[mobject.GetName()] = true - impl.globalMapClusterNamespace[clusterName] = allNamespaces - } else { - allNamespaces := impl.globalMapClusterNamespace[clusterName] - allNamespaces[mobject.GetName()] = true - impl.globalMapClusterNamespace[clusterName] = allNamespaces - } - //mutex.Unlock() + value, _ := impl.globalMapClusterNamespace.Load(clusterName) + allNamespaces := value.(*sync.Map) + allNamespaces.Store(mobject.GetName(), true) } }, DeleteFunc: func(obj interface{}) { if object, ok := obj.(metav1.Object); ok { - mutex.Lock() - defer mutex.Unlock() - if _, ok := impl.globalMapClusterNamespace[clusterName]; ok { - allNamespaces := impl.globalMapClusterNamespace[clusterName] - delete(allNamespaces, object.GetName()) - impl.globalMapClusterNamespace[clusterName] = allNamespaces - //mutex.Unlock() - } + value, _ := impl.globalMapClusterNamespace.Load(clusterName) + allNamespaces := value.(*sync.Map) + allNamespaces.Delete(object.GetName()) } }, }) diff --git a/pkg/pipeline/BuildPipelineConfigService.go b/pkg/pipeline/BuildPipelineConfigService.go index dd4e570d53..225fb5f315 100644 --- a/pkg/pipeline/BuildPipelineConfigService.go +++ b/pkg/pipeline/BuildPipelineConfigService.go @@ -285,6 +285,16 @@ func (impl *CiPipelineConfigServiceImpl) patchCiPipelineUpdateSource(baseCiConfi impl.logger.Errorw("error in fetching pipeline", "id", modifiedCiPipeline.Id, "err", err) return nil, err } + // updating PipelineType from db if not present in request + if modifiedCiPipeline.PipelineType == "" { + if CiPipeline.PipelineType(pipeline.PipelineType) != "" { + modifiedCiPipeline.PipelineType = CiPipeline.PipelineType(pipeline.PipelineType) + } else { + // updating default pipelineType if not present in request + modifiedCiPipeline.PipelineType = CiPipeline.DefaultPipelineType + + } + } if !modifiedCiPipeline.PipelineType.IsValidPipelineType() { impl.logger.Debugw(" Invalid PipelineType", "PipelineType", modifiedCiPipeline.PipelineType) errorMessage := fmt.Sprintf(CiPipeline.PIPELINE_TYPE_IS_NOT_VALID, modifiedCiPipeline.Name) diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 914b434c4f..791c32da73 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -984,7 +984,7 @@ func (impl *CdHandlerImpl) FetchAppWorkflowStatusForTriggerViewForEnvironment(re statusMap := make(map[int]string) if len(wfrIds) > 0 { - cdWorkflowRunners, err := impl.cdWorkflowRepository.FetchAllCdStagesLatestEntityStatus(wfrIds) + cdWorkflowRunners, err := impl.cdWorkflowRepository.FetchEnvAllCdStagesLatestEntityStatus(wfrIds, request.ParentResourceId) if err != nil && !util.IsErrNoRows(err) { return cdWorkflowStatus, err } @@ -1130,7 +1130,7 @@ func (impl *CdHandlerImpl) FetchAppDeploymentStatusForEnvironments(request resou } if len(wfrIds) > 0 { _, span = otel.Tracer("orchestrator").Start(request.Ctx, "pipelineBuilder.FetchAllCdStagesLatestEntityStatus") - wfrList, err := impl.cdWorkflowRepository.FetchAllCdStagesLatestEntityStatus(wfrIds) + wfrList, err := impl.cdWorkflowRepository.FetchEnvAllCdStagesLatestEntityStatus(wfrIds, request.ParentResourceId) span.End() if err != nil && !util.IsErrNoRows(err) { return deploymentStatuses, err diff --git a/pkg/pipeline/CiService.go b/pkg/pipeline/CiService.go index 5a6bbdd6d9..d16dd55199 100644 --- a/pkg/pipeline/CiService.go +++ b/pkg/pipeline/CiService.go @@ -158,19 +158,32 @@ func (impl *CiServiceImpl) GetCiMaterials(pipelineId int, ciMaterials []*pipelin } } +func (impl *CiServiceImpl) handleRuntimeParamsValidations(trigger types.Trigger, ciMaterials []*pipelineConfig.CiPipelineMaterial) error { + // checking if user has given run time parameters for externalCiArtifact, if given then sending git material to Ci-Runner + externalCiArtifact, exists := trigger.ExtraEnvironmentVariables[CiPipeline.ExtraEnvVarExternalCiArtifactKey] + // validate externalCiArtifact as docker image + if exists { + if !strings.Contains(externalCiArtifact, ":") { + impl.Logger.Errorw("validation error", "externalCiArtifact", externalCiArtifact) + return fmt.Errorf("invalid image name given in externalCiArtifact") + } + } + if trigger.PipelineType == string(CiPipeline.CI_JOB) && len(ciMaterials) != 0 && !exists && externalCiArtifact == "" { + ciMaterials[0].GitMaterial = nil + ciMaterials[0].GitMaterialId = 0 + } + return nil +} + func (impl *CiServiceImpl) TriggerCiPipeline(trigger types.Trigger) (int, error) { impl.Logger.Debug("ci pipeline manual trigger") ciMaterials, err := impl.GetCiMaterials(trigger.PipelineId, trigger.CiMaterials) if err != nil { return 0, err } - - // checking if user has given run time parameters for externalCiArtifact, if given then sending git material to Ci-Runner - externalCiArtifact, exists := trigger.ExtraEnvironmentVariables["externalCiArtifact"] - if trigger.PipelineType == string(CiPipeline.CI_JOB) && len(ciMaterials) != 0 && !exists && externalCiArtifact == "" { - ciMaterials = []*pipelineConfig.CiPipelineMaterial{ciMaterials[0]} - ciMaterials[0].GitMaterial = nil - ciMaterials[0].GitMaterialId = 0 + err = impl.handleRuntimeParamsValidations(trigger, ciMaterials) + if err != nil { + return 0, err } ciPipelineScripts, err := impl.ciPipelineRepository.FindCiScriptsByCiPipelineId(trigger.PipelineId) if err != nil && !util.IsErrNoRows(err) { @@ -569,7 +582,7 @@ func (impl *CiServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineConfig. } ciBuildConfigBean = templateOverrideBean.CiBuildConfig // updating args coming from ciBaseBuildConfigEntity because it is not part of Ci override - if ciBuildConfigBean != nil && ciBuildConfigBean.DockerBuildConfig != nil { + if ciBuildConfigBean != nil && ciBuildConfigBean.DockerBuildConfig != nil && ciBaseBuildConfigBean != nil && ciBaseBuildConfigBean.DockerBuildConfig != nil { ciBuildConfigBean.DockerBuildConfig.Args = ciBaseBuildConfigBean.DockerBuildConfig.Args } templateOverride := templateOverrideBean.CiTemplateOverride @@ -734,6 +747,10 @@ func (impl *CiServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineConfig. if pipeline.App.AppType == helper.Job { workflowRequest.AppName = pipeline.App.DisplayName } + if trigger.PipelineType == string(CiPipeline.CI_JOB) { + workflowRequest.IgnoreDockerCachePush = impl.config.SkipCiJobBuildCachePushPull + workflowRequest.IgnoreDockerCachePull = impl.config.SkipCiJobBuildCachePushPull + } if dockerRegistry != nil { workflowRequest.DockerRegistryId = dockerRegistry.Id diff --git a/pkg/pipeline/ConfigMapService.go b/pkg/pipeline/ConfigMapService.go index 77e996dcce..49c08772a1 100644 --- a/pkg/pipeline/ConfigMapService.go +++ b/pkg/pipeline/ConfigMapService.go @@ -34,7 +34,9 @@ import ( util2 "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg" "go.uber.org/zap" + "net/http" "regexp" + "strconv" "time" ) @@ -504,12 +506,19 @@ func (impl ConfigMapServiceImpl) CSGlobalAddUpdate(configMapRequest *bean.Config return nil, fmt.Errorf("invalid request multiple config found for add or update") } configData := configMapRequest.ConfigData[0] + // validating config/secret data at service layer since this func is consumed in multiple flows, hence preventing code duplication valid, err := impl.validateConfigData(configData) if err != nil && !valid { impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } + valid, err = impl.validateConfigDataForSecretsOnly(configData) + if err != nil && !valid { + impl.logger.Errorw("error in validating secrets only data", "error", err) + return configMapRequest, err + } + valid, err = impl.validateExternalSecretChartCompatibility(configMapRequest.AppId, configMapRequest.EnvironmentId, configData) if err != nil && !valid { impl.logger.Errorw("error in validating", "error", err) @@ -704,11 +713,17 @@ func (impl ConfigMapServiceImpl) CSEnvironmentAddUpdate(configMapRequest *bean.C } configData := configMapRequest.ConfigData[0] + // validating config/secret data at service layer since this func is consumed in multiple flows, hence preventing code duplication valid, err := impl.validateConfigData(configData) if err != nil && !valid { impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } + valid, err = impl.validateConfigDataForSecretsOnly(configData) + if err != nil && !valid { + impl.logger.Errorw("error in validating secrets only data", "error", err) + return configMapRequest, err + } valid, err = impl.validateExternalSecretChartCompatibility(configMapRequest.AppId, configMapRequest.EnvironmentId, configData) if err != nil && !valid { @@ -795,13 +810,6 @@ func (impl ConfigMapServiceImpl) CSEnvironmentAddUpdate(configMapRequest *bean.C } configMapRequest.Id = configMap.Id } - //VARIABLE_MAPPING_UPDATE - //sl := bean.SecretsList{} - //data, err := sl.GetTransformedDataForSecretList(model.SecretData, util2.DecodeSecret) - //if err != nil { - // return nil, err - //} - //err = impl.extractAndMapVariables(data, model.Id, repository5.EntityTypeSecretEnvLevel, configMapRequest.UserId) err = impl.scopedVariableManager.CreateVariableMappingsForSecretEnv(model) if err != nil { return nil, err @@ -1545,6 +1553,26 @@ func (impl ConfigMapServiceImpl) validateConfigData(configData *bean.ConfigData) return true, nil } +func (impl ConfigMapServiceImpl) validateConfigDataForSecretsOnly(configData *bean.ConfigData) (bool, error) { + + // check encoding in base64 for secret data + if len(configData.Data) > 0 { + dataMap := make(map[string]string) + err := json.Unmarshal(configData.Data, &dataMap) + if err != nil { + impl.logger.Errorw("error while unmarshalling secret data ", "error", err) + return false, err + } + err = util2.ValidateEncodedDataByDecoding(dataMap) + if err != nil { + impl.logger.Errorw("error in decoding secret data", "error", err) + return false, util.NewApiError().WithHttpStatusCode(http.StatusUnprocessableEntity).WithCode(strconv.Itoa(http.StatusUnprocessableEntity)). + WithUserMessage("error in decoding data, make sure the secret data is encoded properly") + } + } + return true, nil +} + func (impl ConfigMapServiceImpl) updateConfigData(configData *bean.ConfigData, syncRequest *bean.BulkPatchRequest) (*bean.ConfigData, error) { dataMap := make(map[string]string) var updatedData json.RawMessage diff --git a/pkg/pipeline/bean/CiPipeline/CiBuildConfig.go b/pkg/pipeline/bean/CiPipeline/CiBuildConfig.go index 4449861968..0050dc19f3 100644 --- a/pkg/pipeline/bean/CiPipeline/CiBuildConfig.go +++ b/pkg/pipeline/bean/CiPipeline/CiBuildConfig.go @@ -32,6 +32,9 @@ const PIPELINE_TYPE_IS_NOT_VALID = "PipelineType is not valid for pipeline %s" type PipelineType string +// default PipelineType +const DefaultPipelineType = CI_BUILD + const ( CI_BUILD PipelineType = "CI_BUILD" LINKED PipelineType = "LINKED" @@ -82,3 +85,8 @@ func (pType PipelineType) IsValidPipelineType() bool { return false } } + +const ( + ExtraEnvVarExternalCiArtifactKey = "externalCiArtifact" + ExtraEnvVarImageDigestKey = "imageDigest" +) diff --git a/pkg/pipeline/types/CiCdConfig.go b/pkg/pipeline/types/CiCdConfig.go index bf7e82fe3e..50e7d27271 100644 --- a/pkg/pipeline/types/CiCdConfig.go +++ b/pkg/pipeline/types/CiCdConfig.go @@ -82,6 +82,7 @@ type CiCdConfig struct { ImageScanRetryDelay int `env:"IMAGE_SCAN_RETRY_DELAY" envDefault:"5"` ShowDockerBuildCmdInLogs bool `env:"SHOW_DOCKER_BUILD_ARGS" envDefault:"true"` IgnoreCmCsInCiJob bool `env:"IGNORE_CM_CS_IN_CI_JOB" envDefault:"false"` + SkipCiJobBuildCachePushPull bool `env:"SKIP_CI_JOB_BUILD_CACHE_PUSH_PULL" envDefault:"false"` // from CdConfig CdLimitCpu string `env:"CD_LIMIT_CI_CPU" envDefault:"0.5"` CdLimitMem string `env:"CD_LIMIT_CI_MEM" envDefault:"3G"` diff --git a/pkg/sql/connection.go b/pkg/sql/connection.go index 70ef3b62be..88af6a963e 100644 --- a/pkg/sql/connection.go +++ b/pkg/sql/connection.go @@ -33,7 +33,7 @@ type Config struct { Password string `env:"PG_PASSWORD" envDefault:"" secretData:"-"` Database string `env:"PG_DATABASE" envDefault:"orchestrator"` CasbinDatabase string `env:"CASBIN_DATABASE" envDefault:"casbin"` - ApplicationName string `env:"APP" envDefault:"orchestrator"` + ApplicationName string `env:"APP" envDefault:"orchestrator" envDescription:"Application name"` LogQuery bool `env:"PG_LOG_QUERY" envDefault:"true"` LogAllQuery bool `env:"PG_LOG_ALL_QUERY" envDefault:"false"` ExportPromMetrics bool `env:"PG_EXPORT_PROM_METRICS" envDefault:"false"` diff --git a/scripts/sql/270_improved_image_scan_plugin.down.sql b/scripts/sql/270_improved_image_scan_plugin.down.sql new file mode 100644 index 0000000000..66133463b1 --- /dev/null +++ b/scripts/sql/270_improved_image_scan_plugin.down.sql @@ -0,0 +1 @@ +-- empty script to keep script number same across repo \ No newline at end of file diff --git a/scripts/sql/270_improved_image_scan_plugin.up.sql b/scripts/sql/270_improved_image_scan_plugin.up.sql new file mode 100644 index 0000000000..66133463b1 --- /dev/null +++ b/scripts/sql/270_improved_image_scan_plugin.up.sql @@ -0,0 +1 @@ +-- empty script to keep script number same across repo \ No newline at end of file diff --git a/scripts/sql/270_plugin_parent_metadata.down.sql b/scripts/sql/270_plugin_parent_metadata.down.sql deleted file mode 100644 index 4a40f1712a..0000000000 --- a/scripts/sql/270_plugin_parent_metadata.down.sql +++ /dev/null @@ -1,5 +0,0 @@ ----- DROP table -DROP TABLE IF EXISTS "plugin_parent_metadata"; - ----- DROP sequence -DROP SEQUENCE IF EXISTS public.id_seq_plugin_parent_metadata; \ No newline at end of file diff --git a/scripts/sql/271_plugin_parent_metadata.down.sql b/scripts/sql/271_plugin_parent_metadata.down.sql new file mode 100644 index 0000000000..768cdf8ec9 --- /dev/null +++ b/scripts/sql/271_plugin_parent_metadata.down.sql @@ -0,0 +1 @@ +-- empty script \ No newline at end of file diff --git a/scripts/sql/270_plugin_parent_metadata.up.sql b/scripts/sql/271_plugin_parent_metadata.up.sql similarity index 100% rename from scripts/sql/270_plugin_parent_metadata.up.sql rename to scripts/sql/271_plugin_parent_metadata.up.sql diff --git a/scripts/sql/271_alter_plugin_metadata.down.sql b/scripts/sql/272_alter_plugin_metadata.down.sql similarity index 69% rename from scripts/sql/271_alter_plugin_metadata.down.sql rename to scripts/sql/272_alter_plugin_metadata.down.sql index 6a2fa80a8a..90d499e971 100644 --- a/scripts/sql/271_alter_plugin_metadata.down.sql +++ b/scripts/sql/272_alter_plugin_metadata.down.sql @@ -4,4 +4,8 @@ ALTER TABLE plugin_metadata DROP COLUMN IF EXISTS is_deprecated; ALTER TABLE plugin_metadata DROP COLUMN IF EXISTS doc_link; ALTER TABLE plugin_metadata DROP COLUMN IF EXISTS is_latest; -ALTER TABLE plugin_metadata DROP CONSTRAINT plugin_metadata_plugin_parent_metadata_id_fkey; \ No newline at end of file +---- DROP table +DROP TABLE IF EXISTS "plugin_parent_metadata"; + +---- DROP sequence +DROP SEQUENCE IF EXISTS public.id_seq_plugin_parent_metadata; \ No newline at end of file diff --git a/scripts/sql/271_alter_plugin_metadata.up.sql b/scripts/sql/272_alter_plugin_metadata.up.sql similarity index 100% rename from scripts/sql/271_alter_plugin_metadata.up.sql rename to scripts/sql/272_alter_plugin_metadata.up.sql diff --git a/scripts/sql/272_tls_support_in_git.down.sql b/scripts/sql/273_tls_support_in_git.down.sql similarity index 100% rename from scripts/sql/272_tls_support_in_git.down.sql rename to scripts/sql/273_tls_support_in_git.down.sql diff --git a/scripts/sql/272_tls_support_in_git.up.sql b/scripts/sql/273_tls_support_in_git.up.sql similarity index 100% rename from scripts/sql/272_tls_support_in_git.up.sql rename to scripts/sql/273_tls_support_in_git.up.sql diff --git a/scripts/sql/273_system_controller.down.sql b/scripts/sql/274_system_controller.down.sql similarity index 100% rename from scripts/sql/273_system_controller.down.sql rename to scripts/sql/274_system_controller.down.sql diff --git a/scripts/sql/273_system_controller.up.sql b/scripts/sql/274_system_controller.up.sql similarity index 100% rename from scripts/sql/273_system_controller.up.sql rename to scripts/sql/274_system_controller.up.sql diff --git a/scripts/sql/275_policy_criteria_table.down.sql b/scripts/sql/275_policy_criteria_table.down.sql new file mode 100644 index 0000000000..0c7301d740 --- /dev/null +++ b/scripts/sql/275_policy_criteria_table.down.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS resource_qualifier_mapping_criteria CASCADE; + +DELETE from devtron_resource_searchable_key ds where ds."name" in ('GLOBAL_ID', 'BASE_DEPLOYMENT_TEMPLATE'); diff --git a/scripts/sql/275_policy_criteria_table.up.sql b/scripts/sql/275_policy_criteria_table.up.sql new file mode 100644 index 0000000000..2ede7adcdd --- /dev/null +++ b/scripts/sql/275_policy_criteria_table.up.sql @@ -0,0 +1,20 @@ +CREATE SEQUENCE IF NOT EXISTS id_seq_resource_qualifier_mapping_criteria; + +CREATE TABLE IF NOT EXISTS resource_qualifier_mapping_criteria +( + "id" integer NOT NULL DEFAULT nextval('id_seq_resource_qualifier_mapping_criteria'::regclass), + "description" varchar(100), + "json_data" text, + "active" bool, + "created_on" timestamptz NOT NULL, + "created_by" int4 NOT NULL, + "updated_on" timestamptz NOT NULL, + "updated_by" int4 NOT NULL, + PRIMARY KEY ("id") +); + +INSERT INTO devtron_resource_searchable_key(name, is_removed, created_on, created_by, updated_on, updated_by) +VALUES ('BASE_DEPLOYMENT_TEMPLATE', false, now(), 1, now(), 1); + +INSERT INTO devtron_resource_searchable_key(name, is_removed, created_on, created_by, updated_on, updated_by) +VALUES ('GLOBAL_ID', false, now(), 1, now(), 1); \ No newline at end of file diff --git a/scripts/sql/276_alter_pipeline_stage_step_variable.down.sql b/scripts/sql/276_alter_pipeline_stage_step_variable.down.sql new file mode 100644 index 0000000000..bad0b4c492 --- /dev/null +++ b/scripts/sql/276_alter_pipeline_stage_step_variable.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE pipeline_stage_step_variable ALTER COLUMN default_value TYPE VARCHAR(255); +ALTER TABLE pipeline_stage_step_variable ALTER COLUMN value TYPE VARCHAR(255); + diff --git a/scripts/sql/276_alter_pipeline_stage_step_variable.up.sql b/scripts/sql/276_alter_pipeline_stage_step_variable.up.sql new file mode 100644 index 0000000000..cbcf6515c9 --- /dev/null +++ b/scripts/sql/276_alter_pipeline_stage_step_variable.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE pipeline_stage_step_variable ALTER COLUMN value TYPE text; +ALTER TABLE pipeline_stage_step_variable ALTER COLUMN default_value TYPE text; diff --git a/scripts/sql/277_insert_devtron_resource_searchable_key_table.down.sql b/scripts/sql/277_insert_devtron_resource_searchable_key_table.down.sql new file mode 100644 index 0000000000..1909420ca7 --- /dev/null +++ b/scripts/sql/277_insert_devtron_resource_searchable_key_table.down.sql @@ -0,0 +1 @@ +DELETE from devtron_resource_searchable_key ds where ds."name" in ('CHART_NAME'); \ No newline at end of file diff --git a/scripts/sql/277_insert_devtron_resource_searchable_key_table.up.sql b/scripts/sql/277_insert_devtron_resource_searchable_key_table.up.sql new file mode 100644 index 0000000000..4a987ea145 --- /dev/null +++ b/scripts/sql/277_insert_devtron_resource_searchable_key_table.up.sql @@ -0,0 +1,3 @@ + +INSERT INTO devtron_resource_searchable_key(name, is_removed, created_on, created_by, updated_on, updated_by) +VALUES ('CHART_NAME', false, now(), 1, now(), 1); \ No newline at end of file diff --git a/specs/fluxcd_app.yaml b/specs/fluxcd_app.yaml new file mode 100644 index 0000000000..ff83979291 --- /dev/null +++ b/specs/fluxcd_app.yaml @@ -0,0 +1,299 @@ +openapi: 3.0.0 +info: + title: Flux Application Orchestrator API + version: 1.0.0 +paths: + /orchestrator/flux-application: + get: + summary: List Flux Applications + operationId: listFluxApplications + parameters: + - name: token + in: header + required: true + schema: + type: string + description: Authorization token + - name: clusterIds + in: query + required: true + schema: + type: string + description: Comma-separated list of cluster IDs. + responses: + '200': + description: List of Flux applications + content: + application/json: + schema: + $ref: '#/components/schemas/AppListDto' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/flux-application/app: + get: + summary: Get application details + description: Retrieve details of a specific Flux application. + parameters: + - name: appId + in: query + required: true + schema: + type: string + description: The application identifier in the format "1|default|myksApp|Kustomization as the first field having the cluster id, then second field having the namespace of the app , third field denoted the app name and last contains a boolean value of true and false". + - name: token + in: header + required: true + schema: + type: string + description: The authentication token. + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/FluxApplicationDetailDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + +components: + schemas: + AppListDto: + type: object + properties: + clusterIds: + type: array + description: Cluster Id to which the result corresponds + example: [1] + items: + type: integer + fluxApplication: + type: array + description: List of Flux applications + items: + $ref: '#/components/schemas/FluxAppDto' + FluxAppDto: + type: object + properties: + appName: + type: string + description: Name of the application + example: flux-system + appStatus: + type: boolean + enum: [True, False] + description: + example: True + syncStatus: + type: string + description: Sync status of the application + example: "Applied revision: main@sha1:a3c3de4083eca4ca01d63f9f1b07599b64f3f8ca" + clusterId: + type: integer + description: ID of the cluster + example: 2 + clusterName: + type: string + description: Name of the cluster + example: test-cluster-1 + namespace: + type: string + description: Namespace of the application + example: flux-system + fluxAppDeploymentType: + type: string + enum": ["Kustomization", "HelmRelease"] + description: Indicates if the application is a Kustomize type or standalone flux made HelmRelease app + example: true + FluxAppStatusDetail: + type: object + properties: + status: + type: string + description: Tells about the status whether true or false of the last action performed + message: + type: string + description: Brief message of the last encountered reason + reason: + type: string + description: Short key words like 'ReconciliationFailed', 'Reconciled', and so on for the user to understand the reason of the given of the status + + InfoItem: + type: object + properties: + name: + type: string + value: + type: string + + HealthStatus: + type: object + properties: + status: + type: string + message: + type: string + + ResourceNetworkingInfo: + type: object + properties: + labels: + type: object + additionalProperties: + type: string + + ResourceRef: + type: object + properties: + group: + type: string + version: + type: string + kind: + type: string + namespace: + type: string + name: + type: string + uid: + type: string + + PodMetadata: + type: object + properties: + name: + type: string + uid: + type: string + containers: + type: array + items: + type: string + initContainers: + type: array + items: + type: string + isNew: + type: boolean + ephemeralContainers: + type: array + items: + $ref: '#/components/schemas/EphemeralContainerData' + + EphemeralContainerData: + type: object + properties: + name: + type: string + isExternal: + type: boolean + + ResourceNode: + type: object + properties: + group: + type: string + version: + type: string + kind: + type: string + namespace: + type: string + name: + type: string + uid: + type: string + parentRefs: + type: array + items: + $ref: '#/components/schemas/ResourceRef' + networkingInfo: + $ref: '#/components/schemas/ResourceNetworkingInfo' + resourceVersion: + type: string + health: + $ref: '#/components/schemas/HealthStatus' + isHibernated: + type: boolean + canBeHibernated: + type: boolean + info: + type: array + items: + $ref: '#/components/schemas/InfoItem' + createdAt: + type: string + format: date-time + port: + type: array + items: + type: integer + isHook: + type: boolean + hookType: + type: string + + ResourceTreeResponse: + type: object + properties: + nodes: + type: array + items: + $ref: '#/components/schemas/ResourceNode' + podMetadata: + type: array + items: + $ref: '#/components/schemas/PodMetadata' + + FluxApplicationDetailDto: + type: object + properties: + FluxApplication: + $ref: '#/components/schemas/FluxAppDto' + FluxAppStatusDetail: + $ref: '#/components/schemas/FluxAppStatusDetail' + ResourceTreeResponse: + $ref: '#/components/schemas/ResourceTreeResponse' + + Error: + type: object + properties: + message: + type: string + description: Error message + example: unauthorized diff --git a/util/HttpUtil.go b/util/HttpUtil.go index 362ef67812..d28e54688d 100644 --- a/util/HttpUtil.go +++ b/util/HttpUtil.go @@ -107,7 +107,7 @@ func GetTlsConfig(TLSKey, TLSCert, CACert, folderPath string) (*tls.Config, erro return nil, err } } - if len(caCertFileName) > 0 { + if len(CACert) > 0 { caCertFileName = getCertFileName() caCertFilePath, err = CreateFileWithData(folderPath, caCertFileName, CACert) if err != nil { @@ -115,9 +115,10 @@ func GetTlsConfig(TLSKey, TLSCert, CACert, folderPath string) (*tls.Config, erro return nil, err } } - tlsConfig, err := tlsutil.NewClientTLS(caCertFilePath, tlsKeyFilePath, tlsCertFilePath) + tlsConfig, err := tlsutil.NewClientTLS(tlsCertFilePath, tlsKeyFilePath, caCertFilePath) if err != nil { fmt.Printf("error in creating tls config %s ", err) + return nil, err } return tlsConfig, nil } diff --git a/util/encoding-utils.go b/util/encoding-utils.go index 88064a26bd..82837c229c 100644 --- a/util/encoding-utils.go +++ b/util/encoding-utils.go @@ -53,3 +53,13 @@ func GetDecodedAndEncodedData(data json.RawMessage, transformer SecretTransformM } return marshal, nil } + +func ValidateEncodedDataByDecoding(dataMap map[string]string) error { + for _, value := range dataMap { + _, err := base64.StdEncoding.DecodeString(value) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go b/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go index 64c1f61863..7734f432bf 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8s/K8sUtil.go @@ -59,7 +59,6 @@ import ( "k8s.io/client-go/kubernetes" v12 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/rest" - restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "sigs.k8s.io/yaml" ) @@ -72,7 +71,7 @@ type K8sServiceImpl struct { } type K8sService interface { - GetLogsForAPod(kubeClient *kubernetes.Clientset, namespace string, podName string, container string, follow bool) *restclient.Request + GetLogsForAPod(kubeClient *kubernetes.Clientset, namespace string, podName string, container string, follow bool) *rest.Request GetMetricsClientSet(restConfig *rest.Config, k8sHttpClient *http.Client) (*metrics.Clientset, error) GetNmByName(ctx context.Context, metricsClientSet *metrics.Clientset, name string) (*v1beta1.NodeMetrics, error) GetNmList(ctx context.Context, metricsClientSet *metrics.Clientset) (*v1beta1.NodeMetricsList, error) @@ -107,18 +106,20 @@ type K8sService interface { CreateSecretData(namespace string, secret *v1.Secret, v1Client *v12.CoreV1Client) (*v1.Secret, error) CreateSecret(namespace string, data map[string][]byte, secretName string, secretType v1.SecretType, client *v12.CoreV1Client, labels map[string]string, stringData map[string]string) (*v1.Secret, error) GetSecret(namespace string, name string, client *v12.CoreV1Client) (*v1.Secret, error) + GetSecretWithCtx(ctx context.Context, namespace string, name string, client *v12.CoreV1Client) (*v1.Secret, error) PatchConfigMapJsonType(namespace string, clusterConfig *ClusterConfig, name string, data interface{}, path string) (*v1.ConfigMap, error) PatchConfigMap(namespace string, clusterConfig *ClusterConfig, name string, data map[string]interface{}) (*v1.ConfigMap, error) UpdateConfigMap(namespace string, cm *v1.ConfigMap, client *v12.CoreV1Client) (*v1.ConfigMap, error) CreateConfigMap(namespace string, cm *v1.ConfigMap, client *v12.CoreV1Client) (*v1.ConfigMap, error) GetConfigMap(namespace string, name string, client *v12.CoreV1Client) (*v1.ConfigMap, error) + GetConfigMapWithCtx(ctx context.Context, namespace string, name string, client *v12.CoreV1Client) (*v1.ConfigMap, error) CheckIfNsExists(namespace string, client *v12.CoreV1Client) (exists bool, err error) CreateNsIfNotExists(namespace string, clusterConfig *ClusterConfig) (err error) GetK8sDiscoveryClientInCluster() (*discovery.DiscoveryClient, error) GetK8sDiscoveryClient(clusterConfig *ClusterConfig) (*discovery.DiscoveryClient, error) GetClientForInCluster() (*v12.CoreV1Client, error) GetCoreV1Client(clusterConfig *ClusterConfig) (*v12.CoreV1Client, error) - GetRestConfigByCluster(clusterConfig *ClusterConfig) (*restclient.Config, error) + GetRestConfigByCluster(clusterConfig *ClusterConfig) (*rest.Config, error) GetResource(ctx context.Context, namespace string, name string, gvk schema.GroupVersionKind, restConfig *rest.Config) (*ManifestResponse, error) UpdateResource(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string, k8sRequestPatch string) (*ManifestResponse, error) DeleteResource(ctx context.Context, restConfig *rest.Config, gvk schema.GroupVersionKind, namespace string, name string, forceDelete bool) (*ManifestResponse, error) @@ -138,6 +139,11 @@ type K8sService interface { CreateK8sClientSet(restConfig *rest.Config) (*kubernetes.Clientset, error) CreateOrUpdateSecretByName(client *v12.CoreV1Client, namespace, uniqueSecretName string, secretLabel map[string]string, secretData map[string]string) error //CreateK8sClientSetWithCustomHttpTransport(restConfig *rest.Config) (*kubernetes.Clientset, error) + + //below functions are exposed for K8sUtilExtended + GetRestConfigByClusterWithoutCustomTransport(clusterConfig *ClusterConfig) (*rest.Config, error) + OverrideRestConfigWithCustomTransport(restConfig *rest.Config) (*rest.Config, error) + CreateNs(namespace string, client *v12.CoreV1Client) (ns *v1.Namespace, err error) } func NewK8sUtil(logger *zap.SugaredLogger, runTimeConfig *RuntimeConfig) *K8sServiceImpl { @@ -155,7 +161,20 @@ func NewK8sUtil(logger *zap.SugaredLogger, runTimeConfig *RuntimeConfig) *K8sSer return &K8sServiceImpl{logger: logger, runTimeConfig: runTimeConfig, kubeconfig: kubeconfig, httpClientConfig: httpClientConfig} } -func (impl *K8sServiceImpl) GetRestConfigByCluster(clusterConfig *ClusterConfig) (*restclient.Config, error) { +func (impl *K8sServiceImpl) GetRestConfigByCluster(clusterConfig *ClusterConfig) (*rest.Config, error) { + restConfig, err := impl.GetRestConfigByClusterWithoutCustomTransport(clusterConfig) + if err != nil { + impl.logger.Errorw("error, GetRestConfigByClusterWithoutCustomTransport", "err", err) + return nil, err + } + restConfig, err = impl.OverrideRestConfigWithCustomTransport(restConfig) + if err != nil { + impl.logger.Errorw("error in overriding rest config with custom transport configurations", "err", err) + } + return restConfig, err +} + +func (impl *K8sServiceImpl) GetRestConfigByClusterWithoutCustomTransport(clusterConfig *ClusterConfig) (*rest.Config, error) { bearerToken := clusterConfig.BearerToken var restConfig *rest.Config var err error @@ -169,11 +188,17 @@ func (impl *K8sServiceImpl) GetRestConfigByCluster(clusterConfig *ClusterConfig) restConfig = &rest.Config{Host: clusterConfig.Host, BearerToken: bearerToken} clusterConfig.PopulateTlsConfigurationsInto(restConfig) } + return restConfig, nil +} + +func (impl *K8sServiceImpl) OverrideRestConfigWithCustomTransport(restConfig *rest.Config) (*rest.Config, error) { + var err error restConfig, err = impl.httpClientConfig.OverrideConfigWithCustomTransport(restConfig) if err != nil { impl.logger.Errorw("error in overriding rest config with custom transport configurations", "err", err) + return nil, err } - return restConfig, err + return restConfig, nil } func (impl *K8sServiceImpl) GetCoreV1Client(clusterConfig *ClusterConfig) (*v12.CoreV1Client, error) { @@ -281,7 +306,7 @@ func (impl *K8sServiceImpl) CreateNsIfNotExists(namespace string, clusterConfig return nil } impl.logger.Infow("ns not exists creating", "ns", namespace) - _, err = impl.createNs(namespace, v12Client) + _, err = impl.CreateNs(namespace, v12Client) return err } @@ -300,7 +325,7 @@ func (impl *K8sServiceImpl) CheckIfNsExists(namespace string, client *v12.CoreV1 } -func (impl *K8sServiceImpl) createNs(namespace string, client *v12.CoreV1Client) (ns *v1.Namespace, err error) { +func (impl *K8sServiceImpl) CreateNs(namespace string, client *v12.CoreV1Client) (ns *v1.Namespace, err error) { nsSpec := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} ns, err = client.Namespaces().Create(context.Background(), nsSpec, metav1.CreateOptions{}) if err != nil { @@ -317,7 +342,11 @@ func (impl *K8sServiceImpl) deleteNs(namespace string, client *v12.CoreV1Client) } func (impl *K8sServiceImpl) GetConfigMap(namespace string, name string, client *v12.CoreV1Client) (*v1.ConfigMap, error) { - cm, err := client.ConfigMaps(namespace).Get(context.Background(), name, metav1.GetOptions{}) + return impl.GetConfigMapWithCtx(context.Background(), namespace, name, client) +} + +func (impl *K8sServiceImpl) GetConfigMapWithCtx(ctx context.Context, namespace string, name string, client *v12.CoreV1Client) (*v1.ConfigMap, error) { + cm, err := client.ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{}) if err != nil { impl.logger.Errorw("error in getting config map", "err", err) return nil, err @@ -355,6 +384,7 @@ func (impl *K8sServiceImpl) PatchConfigMap(namespace string, clusterConfig *Clus b, err := json.Marshal(data) if err != nil { impl.logger.Errorw("error in marshalling data", "err", err) + // TODO: why panic panic(err) } cm, err := k8sClient.ConfigMaps(namespace).Patch(context.Background(), name, types.PatchType(types.MergePatchType), b, metav1.PatchOptions{}) @@ -383,6 +413,7 @@ func (impl *K8sServiceImpl) PatchConfigMapJsonType(namespace string, clusterConf b, err := json.Marshal(patches) if err != nil { impl.logger.Errorw("error in getting marshalling pacthes", "err", err, "namespace", namespace) + // TODO: why panic panic(err) } @@ -403,7 +434,11 @@ type JsonPatchType struct { } func (impl *K8sServiceImpl) GetSecret(namespace string, name string, client *v12.CoreV1Client) (*v1.Secret, error) { - secret, err := client.Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{}) + return impl.GetSecretWithCtx(context.Background(), namespace, name, client) +} + +func (impl *K8sServiceImpl) GetSecretWithCtx(ctx context.Context, namespace string, name string, client *v12.CoreV1Client) (*v1.Secret, error) { + secret, err := client.Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) if err != nil { impl.logger.Errorw("error in getting secrets", "err", err, "namespace", namespace) return nil, err @@ -1075,7 +1110,7 @@ func (impl *K8sServiceImpl) GetMetricsClientSet(restConfig *rest.Config, k8sHttp } return metricsClientSet, err } -func (impl *K8sServiceImpl) GetLogsForAPod(kubeClient *kubernetes.Clientset, namespace string, podName string, container string, follow bool) *restclient.Request { +func (impl *K8sServiceImpl) GetLogsForAPod(kubeClient *kubernetes.Clientset, namespace string, podName string, container string, follow bool) *rest.Request { podLogOpts := &v1.PodLogOptions{ Container: container, Follow: follow, diff --git a/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go b/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go index ac429273ad..05f5220ea2 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/k8s/bean.go @@ -234,7 +234,7 @@ func (impl *CustomK8sHttpTransportConfig) OverrideConfigWithCustomTransport(conf } transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: http.ProxyFromEnvironment, + Proxy: config.Proxy, TLSHandshakeTimeout: time.Duration(impl.TLSHandshakeTimeout) * time.Second, TLSClientConfig: tlsConfig, MaxIdleConns: impl.MaxIdleConnsPerHost, diff --git a/vendor/modules.txt b/vendor/modules.txt index 9b1a931cb6..b9a17ac490 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -401,7 +401,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.0.25-0.20240809073131-5cefb0e8a93a +# github.com/devtron-labs/common-lib v0.0.25-0.20240812113340-f14be466613d ## explicit; go 1.21 github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage diff --git a/wire_gen.go b/wire_gen.go index bfc84a3cc5..d83a360fd0 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -31,6 +31,7 @@ import ( deployment2 "github.com/devtron-labs/devtron/api/deployment" devtronResource2 "github.com/devtron-labs/devtron/api/devtronResource" externalLink2 "github.com/devtron-labs/devtron/api/externalLink" + fluxApplication2 "github.com/devtron-labs/devtron/api/fluxApplication" client3 "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/api/helm-app/service" @@ -163,6 +164,7 @@ import ( "github.com/devtron-labs/devtron/pkg/eventProcessor/in" "github.com/devtron-labs/devtron/pkg/eventProcessor/out" "github.com/devtron-labs/devtron/pkg/externalLink" + "github.com/devtron-labs/devtron/pkg/fluxApplication" "github.com/devtron-labs/devtron/pkg/generateManifest" "github.com/devtron-labs/devtron/pkg/genericNotes" repository6 "github.com/devtron-labs/devtron/pkg/genericNotes/repository" @@ -265,8 +267,8 @@ func InitializeApp() (*App, error) { return nil, err } serviceClientImpl := cluster.NewServiceClientImpl(sugaredLogger, argoCDConnectionManagerImpl) - v := informer.NewGlobalMapClusterNamespace() - k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v, k8sServiceImpl) + syncMap := informer.NewGlobalMapClusterNamespace() + k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, syncMap, k8sServiceImpl) defaultAuthPolicyRepositoryImpl := repository4.NewDefaultAuthPolicyRepositoryImpl(db, sugaredLogger) defaultAuthRoleRepositoryImpl := repository4.NewDefaultAuthRoleRepositoryImpl(db, sugaredLogger) userAuthRepositoryImpl := repository4.NewUserAuthRepositoryImpl(db, sugaredLogger, defaultAuthPolicyRepositoryImpl, defaultAuthRoleRepositoryImpl) @@ -392,7 +394,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, argoUserServiceImpl, helmAppServiceImpl) + argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImplExtended, argoApplicationServiceImpl) environmentRestHandlerImpl := cluster3.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceExtendedImpl, k8sServiceImpl, k8sCommonServiceImpl) environmentRouterImpl := cluster3.NewEnvironmentRouterImpl(environmentRestHandlerImpl) @@ -707,11 +709,12 @@ func InitializeApp() (*App, error) { ephemeralContainersRepositoryImpl := repository.NewEphemeralContainersRepositoryImpl(db, transactionUtilImpl) ephemeralContainerServiceImpl := cluster2.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImplExtended, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationServiceImpl) - k8sApplicationServiceImpl, err := application2.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImplExtended, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl) + fluxApplicationServiceImpl := fluxApplication.NewFluxApplicationServiceImpl(sugaredLogger, helmAppServiceImpl, clusterServiceImplExtended, helmAppClientImpl, pumpImpl) + k8sApplicationServiceImpl, err := application2.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImplExtended, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl, fluxApplicationServiceImpl) if err != nil { return nil, err } - installedAppResourceServiceImpl := resource.NewInstalledAppResourceServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, applicationServiceClientImpl, acdAuthConfig, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, k8sServiceImpl, deploymentConfigServiceImpl) + installedAppResourceServiceImpl := resource.NewInstalledAppResourceServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, applicationServiceClientImpl, acdAuthConfig, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, k8sServiceImpl, deploymentConfigServiceImpl, ociRegistryConfigRepositoryImpl) chartGroupEntriesRepositoryImpl := repository17.NewChartGroupEntriesRepositoryImpl(db, sugaredLogger) chartGroupReposotoryImpl := repository17.NewChartGroupReposotoryImpl(db, sugaredLogger) chartGroupDeploymentRepositoryImpl := repository17.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) @@ -860,9 +863,9 @@ func InitializeApp() (*App, error) { appRouterImpl := app3.NewAppRouterImpl(appFilteringRouterImpl, appListingRouterImpl, appInfoRouterImpl, pipelineTriggerRouterImpl, pipelineConfigRouterImpl, pipelineHistoryRouterImpl, pipelineStatusRouterImpl, appWorkflowRouterImpl, devtronAppAutoCompleteRouterImpl, appWorkflowRestHandlerImpl, appListingRestHandlerImpl, appFilteringRestHandlerImpl) coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl, ciPipelineRepositoryImpl) coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) - helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) + helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig, fluxApplicationServiceImpl, argoApplicationServiceImpl) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) - k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables) + k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables, fluxApplicationServiceImpl, argoApplicationServiceImpl) k8sApplicationRouterImpl := application3.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) pProfRestHandlerImpl := restHandler.NewPProfRestHandler(userServiceImpl, enforcerImpl) pProfRouterImpl := router.NewPProfRouter(sugaredLogger, pProfRestHandlerImpl) @@ -948,7 +951,9 @@ func InitializeApp() (*App, error) { historyRestHandlerImpl := devtronResource2.NewHistoryRestHandlerImpl(sugaredLogger, enforcerImpl, deploymentHistoryServiceImpl, apiReqDecoderServiceImpl, enforcerUtilImpl) historyRouterImpl := devtronResource2.NewHistoryRouterImpl(historyRestHandlerImpl) devtronResourceRouterImpl := devtronResource2.NewDevtronResourceRouterImpl(historyRouterImpl) - muxRouter := router.NewMuxRouter(sugaredLogger, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, userRouterImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, userAttributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImplExtended, bulkUpdateRouterImpl, webhookListenerRouterImpl, appRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl, deploymentConfigRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, globalPluginRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, cdApplicationStatusUpdateHandlerImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, globalCMCSRouterImpl, userTerminalAccessRouterImpl, jobRouterImpl, ciStatusUpdateCronImpl, resourceGroupingRouterImpl, rbacRoleRouterImpl, scopedVariableRouterImpl, ciTriggerCronImpl, proxyRouterImpl, infraConfigRouterImpl, argoApplicationRouterImpl, devtronResourceRouterImpl) + fluxApplicationRestHandlerImpl := fluxApplication2.NewFluxApplicationRestHandlerImpl(fluxApplicationServiceImpl, sugaredLogger, enforcerImpl) + fluxApplicationRouterImpl := fluxApplication2.NewFluxApplicationRouterImpl(fluxApplicationRestHandlerImpl) + muxRouter := router.NewMuxRouter(sugaredLogger, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, userRouterImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, userAttributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImplExtended, bulkUpdateRouterImpl, webhookListenerRouterImpl, appRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl, deploymentConfigRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, globalPluginRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, cdApplicationStatusUpdateHandlerImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, globalCMCSRouterImpl, userTerminalAccessRouterImpl, jobRouterImpl, ciStatusUpdateCronImpl, resourceGroupingRouterImpl, rbacRoleRouterImpl, scopedVariableRouterImpl, ciTriggerCronImpl, proxyRouterImpl, infraConfigRouterImpl, argoApplicationRouterImpl, devtronResourceRouterImpl, fluxApplicationRouterImpl) loggingMiddlewareImpl := util4.NewLoggingMiddlewareImpl(userServiceImpl) cdWorkflowServiceImpl := cd.NewCdWorkflowServiceImpl(sugaredLogger, cdWorkflowRepositoryImpl) cdWorkflowRunnerServiceImpl := cd.NewCdWorkflowRunnerServiceImpl(sugaredLogger, cdWorkflowRepositoryImpl)